diff --git a/Cargo.lock b/Cargo.lock index 97e18d90c95c112f9be8c4a1a0f3a96beedbe2da..e5746f0e7957af78c21f047911742790d87ff874 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -390,6 +390,7 @@ dependencies = [ "serde 1.0.86 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unwrap 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -403,6 +404,7 @@ dependencies = [ "dup-currency-params 0.1.0", "durs-common-tests-tools 0.1.0", "durs-common-tools 0.1.0", + "durs-conf 0.2.0-a", "durs-module 0.2.0-a", "durs-wot 0.8.0-a0.9", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -478,6 +480,7 @@ version = "0.2.0-a" dependencies = [ "dubp-documents 0.12.0", "dup-crypto 0.6.0", + "dup-currency-params 0.1.0", "durs-blockchain-dal 0.2.0-a", "durs-module 0.2.0-a", "durs-network 0.2.0-a", diff --git a/lib/core/conf/src/constants.rs b/lib/core/conf/src/constants.rs index 46661d5b156a5bef7238ddc5fd6830d0473973e1..3535cb46cff83bdfe030e51e4bc567ad633760c5 100644 --- a/lib/core/conf/src/constants.rs +++ b/lib/core/conf/src/constants.rs @@ -25,7 +25,7 @@ pub static CONF_FILENAME: &'static str = "conf.json"; pub static KEYPAIRS_FILENAME: &'static str = "keypairs.json"; /// If no currency is specified by the user, is the currency will be chosen by default -pub static DEFAULT_CURRRENCY: &'static str = "g1"; +pub static DEFAULT_CURRENCY: &'static str = "g1"; /// Default value for `default_sync_module` conf field pub static DEFAULT_DEFAULT_SYNC_MODULE: &'static str = "ws2p"; diff --git a/lib/core/conf/src/lib.rs b/lib/core/conf/src/lib.rs index 061f15a262dc6eda2f1bf88f87e1796caf6420f3..a82f2c9592958ca6f70aafeefd8fdfdc3e0933cf 100644 --- a/lib/core/conf/src/lib.rs +++ b/lib/core/conf/src/lib.rs @@ -109,7 +109,7 @@ pub struct DuRsConfV1 { impl Default for DuRsConfV1 { fn default() -> Self { DuRsConfV1 { - currency: CurrencyName(String::from(constants::DEFAULT_CURRRENCY)), + currency: CurrencyName(String::from(constants::DEFAULT_CURRENCY)), my_node_id: generate_random_node_id(), modules: ModulesConf::default(), disabled: HashSet::with_capacity(0), @@ -174,7 +174,7 @@ pub struct DuRsConfV2 { impl Default for DuRsConfV2 { fn default() -> Self { DuRsConfV2 { - currency: CurrencyName(String::from(constants::DEFAULT_CURRRENCY)), + currency: CurrencyName(String::from(constants::DEFAULT_CURRENCY)), my_node_id: generate_random_node_id(), default_sync_module: ModuleName(String::from(constants::DEFAULT_DEFAULT_SYNC_MODULE)), ressources_usage: ResourcesUsage::default(), @@ -455,7 +455,11 @@ pub fn datas_path(profile_path: PathBuf, currency: &CurrencyName) -> PathBuf { let mut datas_path = profile_path; datas_path.push(currency.to_string()); if !datas_path.as_path().exists() { - fs::create_dir(datas_path.as_path()).expect("Impossible to create currency dir !"); + if let Err(io_error) = fs::create_dir(datas_path.as_path()) { + if io_error.kind() != std::io::ErrorKind::AlreadyExists { + fatal_error!("Impossible to create currency dir !"); + } + } } datas_path } @@ -712,15 +716,7 @@ pub fn write_conf_file<DC: DursConfTrait>( /// Returns the path to the database containing the blockchain pub fn get_blockchain_db_path(profile_path: PathBuf, currency: &CurrencyName) -> PathBuf { - let mut db_path = profile_path; - db_path.push(¤cy.0); - if !db_path.as_path().exists() { - if let Err(io_error) = fs::create_dir(db_path.as_path()) { - if io_error.kind() != std::io::ErrorKind::AlreadyExists { - fatal_error!("Impossible to create currency dir !"); - } - } - } + let mut db_path = datas_path(profile_path, currency); db_path.push("blockchain/"); if !db_path.as_path().exists() { if let Err(io_error) = fs::create_dir(db_path.as_path()) { @@ -732,19 +728,6 @@ pub fn get_blockchain_db_path(profile_path: PathBuf, currency: &CurrencyName) -> db_path } -/// Returns the path to the binary file containing the state of the web of trust -pub fn get_wot_path(profile: String, currency: &CurrencyName) -> PathBuf { - let mut wot_path = match dirs::config_dir() { - Some(path) => path, - None => panic!("Impossible to get your home dir!"), - }; - wot_path.push(constants::USER_DATAS_FOLDER); - wot_path.push(profile); - wot_path.push(currency.to_string()); - wot_path.push("wot.bin"); - wot_path -} - #[cfg(test)] mod tests { use super::*; diff --git a/lib/core/core/src/router.rs b/lib/core/core/src/router.rs index ec9441c329b0335fe195ed369c9ae8a269df7967..ab6e40c1dae730db0daa88dd3ea5b460643795e7 100644 --- a/lib/core/core/src/router.rs +++ b/lib/core/core/src/router.rs @@ -156,7 +156,8 @@ fn start_broadcasting_thread( reserved_apis_parts.insert(module_static_name, module_reserved_apis_parts); // Add module endpoints to local node endpoints local_node_endpoints.append(&mut module_endpoints); - // Send endpoints to network module + + // If all modules registered if expected_registrations_count.is_some() && registrations_count == expected_registrations_count.unwrap() { @@ -165,7 +166,7 @@ fn start_broadcasting_thread( .get(&ModuleRole::InterNodesNetwork) .expect("Fatal error : no module with role InterNodesNetwork !") .to_vec(); - // Send endpoints to receivers + // Send endpoints to network module send_msg_to_several_receivers( DursMsg::ModulesEndpoints(local_node_endpoints.clone()), &receivers, @@ -184,7 +185,7 @@ fn start_broadcasting_thread( } => { // the node to be started less than MAX_REGISTRATION_DELAY 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, msg.clone(), &mut pool_msgs); + store_msg_in_pool(start_time, &msg, &mut pool_msgs); // Get list of receivers let receivers = events_subscriptions .get(&event_type) @@ -199,7 +200,7 @@ fn start_broadcasting_thread( DursMsg::Request { req_to: role, .. } => { // If the node to be started less than MAX_REGISTRATION_DELAY 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, msg.clone(), &mut pool_msgs); + store_msg_in_pool(start_time, &msg, &mut pool_msgs); // Get list of receivers let receivers = roles.get(&role).unwrap_or(&Vec::with_capacity(0)).to_vec(); @@ -284,7 +285,7 @@ fn send_msg_to_several_receivers( /// 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, - msg: DursMsg, + msg: &DursMsg, pool_msgs: &mut HashMap<DursMsgReceiver, Vec<DursMsg>>, ) { if SystemTime::now() @@ -294,13 +295,16 @@ fn store_msg_in_pool( < *MAX_REGISTRATION_DELAY { let msg_recv = match msg { - DursMsg::Event { event_type, .. } => Some(DursMsgReceiver::Event(event_type)), - DursMsg::Request { req_to, .. } => Some(DursMsgReceiver::Role(req_to)), - DursMsg::Response { res_to, .. } => Some(DursMsgReceiver::One(res_to)), + DursMsg::Event { event_type, .. } => Some(DursMsgReceiver::Event(*event_type)), + DursMsg::Request { req_to, .. } => Some(DursMsgReceiver::Role(*req_to)), + DursMsg::Response { res_to, .. } => Some(DursMsgReceiver::One(*res_to)), _ => None, }; if let Some(msg_recv) = msg_recv { - pool_msgs.entry(msg_recv).or_insert_with(Vec::new).push(msg); + pool_msgs + .entry(msg_recv) + .or_insert_with(Vec::new) + .push(msg.clone()); } } else if !pool_msgs.is_empty() { // Clear pool_msgs diff --git a/lib/core/message/Cargo.toml b/lib/core/message/Cargo.toml index b8ed71955daa8ead3bf4ec07299de7c855268915..50109a742972b54e9fcf57cf28c60deaa85244ea 100644 --- a/lib/core/message/Cargo.toml +++ b/lib/core/message/Cargo.toml @@ -7,10 +7,11 @@ license = "AGPL-3.0" edition = "2018" [lib] -path = "lib.rs" +path = "src/lib.rs" [dependencies] dup-crypto = { path = "../../tools/crypto" } +dup-currency-params = { path = "../../tools/currency-params" } dubp-documents= { path = "../../tools/documents" } durs-module = { path = "../module" } durs-network = { path = "../network" } diff --git a/lib/core/message/events.rs b/lib/core/message/src/events.rs similarity index 95% rename from lib/core/message/events.rs rename to lib/core/message/src/events.rs index b3d8311df33efb9971a65a63f567c7eae87909c0..cefd7c3999b162236f6066a4a33e7cf3dd6a4013 100644 --- a/lib/core/message/events.rs +++ b/lib/core/message/src/events.rs @@ -46,6 +46,8 @@ pub enum MemPoolEvent { #[derive(Debug, Clone)] /// Blockchain module events pub enum BlockchainEvent { + /// Currency parameters + CurrencyParameters(dup_currency_params::CurrencyParameters), /// Stack up new valid block in local blockchain StackUpValidBlock(Box<BlockDocument>), /// Revert blocks in local blockchain diff --git a/lib/core/message/lib.rs b/lib/core/message/src/lib.rs similarity index 100% rename from lib/core/message/lib.rs rename to lib/core/message/src/lib.rs diff --git a/lib/core/message/requests.rs b/lib/core/message/src/requests.rs similarity index 100% rename from lib/core/message/requests.rs rename to lib/core/message/src/requests.rs diff --git a/lib/core/message/responses.rs b/lib/core/message/src/responses.rs similarity index 100% rename from lib/core/message/responses.rs rename to lib/core/message/src/responses.rs diff --git a/lib/core/module/src/lib.rs b/lib/core/module/src/lib.rs index 609a57a9a90ed2bf8bf30d3009f794bf4a585da6..6e8f96ed6c5f819f1eff3acb297e431b0f680174 100644 --- a/lib/core/module/src/lib.rs +++ b/lib/core/module/src/lib.rs @@ -198,6 +198,9 @@ pub enum ModuleRole { ///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 { + /// Currency parameters are defined + /// This happens either at the start of the node if it's already synchronized on a currency, or at the 1st synchronization on a currency + CurrencyParameters, /// A new block has been received from the network NewBlockFromNetwork, /// A new transaction has been received from a client software. @@ -212,9 +215,9 @@ pub enum ModuleEvent { NewFork, /// Blockchain rooling back RevertBlocks, - /// A new transaction has been integrated into the local waiting room + /// A new transaction has been integrated into the local mempool NewTxinPool, - /// A new wot document has been integrated into the local waiting room + /// A new wot document has been integrated into the local mempool NewWotDocInPool, /// A new valid HEAD has been received from the network NewValidHeadFromNetwork, diff --git a/lib/modules/blockchain/blockchain-dal/Cargo.toml b/lib/modules/blockchain/blockchain-dal/Cargo.toml index 3c1e073b9b21c40562f615fae6b0158aa8724026..41d1aaa19cd50f0dc89ed04fc5fdbe047434c7fe 100644 --- a/lib/modules/blockchain/blockchain-dal/Cargo.toml +++ b/lib/modules/blockchain/blockchain-dal/Cargo.toml @@ -13,6 +13,7 @@ path = "src/lib.rs" dup-crypto = { path = "../../../tools/crypto" } dup-currency-params = { path = "../../../tools/currency-params" } dubp-documents= { path = "../../../tools/documents" } +durs-conf = { path = "../../../core/conf" } durs-module = { path = "../../../core/module" } durs-common-tools = { path = "../../../tools/common-tools" } durs-wot = { path = "../../../tools/wot" } @@ -23,11 +24,11 @@ rustbreak = {version = "2.0.0-rc3", features = ["bin_enc"]} serde = "1.0.*" serde_derive = "1.0.*" serde_json = "1.0.*" +unwrap = "1.2.1" [dev-dependencies] dup-crypto-tests-tools = { path = "../../../tests-tools/crypto-tests-tools" } dubp-documents-tests-tools = { path = "../../../tests-tools/documents-tests-tools" } durs-common-tests-tools = { path = "../../../tests-tools/common-tests-tools" } -unwrap = "1.2.1" [features] diff --git a/lib/modules/blockchain/blockchain-dal/src/constants.rs b/lib/modules/blockchain/blockchain-dal/src/constants.rs index b463e122bf88a11ce5bf9c28e835ee148f4da3ef..780d8a5499349bbabf4dbe4f4900c2e106e4e065 100644 --- a/lib/modules/blockchain/blockchain-dal/src/constants.rs +++ b/lib/modules/blockchain/blockchain-dal/src/constants.rs @@ -15,3 +15,6 @@ /// Default page size for requests responses pub static DEFAULT_PAGE_SIZE: &'static usize = &50; + +/// Currency parameters DB name +pub const CURRENCY_PARAMS_DB_NAME: &str = "params.db"; diff --git a/lib/modules/blockchain/blockchain-dal/src/lib.rs b/lib/modules/blockchain/blockchain-dal/src/lib.rs index 8a988e64d15b28d19ba90f76351cf81d06d662e7..44b7e54006bf4c4b91367a3a8347e1b5fe09aad7 100644 --- a/lib/modules/blockchain/blockchain-dal/src/lib.rs +++ b/lib/modules/blockchain/blockchain-dal/src/lib.rs @@ -78,7 +78,7 @@ use crate::entities::sources::{SourceAmount, UTXOContentV10, UTXOIndexV10}; use crate::writers::transaction::DALTxV10; /// Currency parameters (Protocol V10) -pub type CurrencyParamsV10Datas = (CurrencyName, BlockV10Parameters); +pub type CurrencyParamsV10Datas = Option<(CurrencyName, BlockV10Parameters)>; /// All blocks of local blockchain indexed by block number pub type LocalBlockchainV10Datas = FnvHashMap<BlockNumber, DALBlock>; /// Forks tree meta datas (block number and hash only) diff --git a/lib/modules/blockchain/blockchain-dal/src/readers/currency_params.rs b/lib/modules/blockchain/blockchain-dal/src/readers/currency_params.rs index f3bd13dfe461702525011a9838c475c473e5699b..a23c2ac5007a9e5a4183e9dd086ff24d1ded6f7b 100644 --- a/lib/modules/blockchain/blockchain-dal/src/readers/currency_params.rs +++ b/lib/modules/blockchain/blockchain-dal/src/readers/currency_params.rs @@ -13,25 +13,56 @@ // 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/>. +use crate::constants::CURRENCY_PARAMS_DB_NAME; use crate::*; +use dubp_documents::documents::block::BlockDocument; use dup_currency_params::CurrencyParameters; +use durs_conf::constants::DEFAULT_CURRENCY; +use unwrap::unwrap; /// Get currency parameters -pub fn get_currency_params( - blockchain_db: &BinDB<LocalBlockchainV10Datas>, -) -> Result<Option<CurrencyParameters>, DALError> { - Ok(blockchain_db.read(|db| { - if let Some(genesis_block) = db.get(&BlockNumber(0)) { - if genesis_block.block.parameters.is_some() { - Some(CurrencyParameters::from(( - genesis_block.block.currency.clone(), - genesis_block.block.parameters.expect("safe unwrap"), - ))) - } else { - fatal_error!("The genesis block are None parameters !"); - } - } else { - None - } +pub fn get_currency_params(db_path: &PathBuf) -> Result<Option<CurrencyParameters>, DALError> { + let currency_params_db = + open_file_db::<CurrencyParamsV10Datas>(db_path, CURRENCY_PARAMS_DB_NAME) + .expect("Fail to open params db"); + Ok(currency_params_db.read(|db| { + db.as_ref().map(|(currency_name, block_genesis_params)| { + CurrencyParameters::from((currency_name.clone(), *block_genesis_params)) + }) })?) } + +/// Get and write currency params +pub fn get_and_write_currency_params( + db_path: &PathBuf, + genesis_block: &BlockDocument, +) -> CurrencyParameters { + if genesis_block.number.0 != 0 { + fatal_error!("The genesis block must have number equal to zero !"); + } else if genesis_block.parameters.is_none() { + fatal_error!("The genesis block must have parameters !"); + } else { + let currency_params_db = BinDB::File( + open_file_db::<CurrencyParamsV10Datas>(&db_path, CURRENCY_PARAMS_DB_NAME) + .expect("Fail to open params db"), + ); + if genesis_block.currency.0 != DEFAULT_CURRENCY { + let mut default_currency_path = db_path.clone(); + default_currency_path.push(DEFAULT_CURRENCY); + let _ = std::fs::remove_file(default_currency_path.as_path()); + } + currency_params_db + .write(|db| { + db.replace(( + genesis_block.currency.clone(), + unwrap!(genesis_block.parameters), + )); + }) + .expect("fail to write in params DB"); + currency_params_db.save().expect("Fail to save params db"); + CurrencyParameters::from(( + genesis_block.currency.clone(), + unwrap!(genesis_block.parameters), + )) + } +} diff --git a/lib/modules/blockchain/blockchain/Cargo.toml b/lib/modules/blockchain/blockchain/Cargo.toml index a4b78d42dca12b737e8430b55efe42fd4aad716d..f4e6184ff309931f5fd7d58e783a765f23e4c2d8 100644 --- a/lib/modules/blockchain/blockchain/Cargo.toml +++ b/lib/modules/blockchain/blockchain/Cargo.toml @@ -31,6 +31,7 @@ rayon = "1.0.3" serde = "1.0.*" serde_json = "1.0.*" threadpool = "1.7.*" +unwrap = "1.2.1" [dev-dependencies] dup-crypto-tests-tools = { path = "../../../tests-tools/crypto-tests-tools" } diff --git a/lib/modules/blockchain/blockchain/clippy.toml b/lib/modules/blockchain/blockchain/clippy.toml index 7833baeacef636c9ba898570627d6385737b8ae8..8abf523b0678976bb8ed0acb66f0be7e1cc83afe 100644 --- a/lib/modules/blockchain/blockchain/clippy.toml +++ b/lib/modules/blockchain/blockchain/clippy.toml @@ -1,2 +1,2 @@ -cyclomatic-complexity-threshold = 42 +cyclomatic-complexity-threshold = 46 too-many-arguments-threshold = 8 \ No newline at end of file diff --git a/lib/modules/blockchain/blockchain/src/constants.rs b/lib/modules/blockchain/blockchain/src/constants.rs index 9b477e696512cb5cf8863b2ea128219c7be79542..434eada8f03f08e2d8f8d74ff2fde041fa85ace6 100644 --- a/lib/modules/blockchain/blockchain/src/constants.rs +++ b/lib/modules/blockchain/blockchain/src/constants.rs @@ -27,3 +27,12 @@ pub static CHUNK_FILE_NAME_BEGIN: &'static str = "chunk_"; /// Chunk file name end pub static CHUNK_FILE_NAME_END: &'static str = "-250.json"; + +/// Low requency of request of main blocks +pub static REQUEST_MAIN_BLOCKS_LOW_FREQUENCY_IN_SEC: &'static u64 = &90; + +/// High frequency of request of the main blocks +pub static REQUEST_MAIN_BLOCKS_HIGH_FREQUENCY_IN_SEC: &'static u64 = &20; + +/// Blocks Delay threshold +pub static BLOCKS_DELAY_THRESHOLD: &'static u32 = &5; diff --git a/lib/modules/blockchain/blockchain/src/dbex.rs b/lib/modules/blockchain/blockchain/src/dbex.rs index f362bd65d9fe78fccece35020d2fab9251437f9f..a41a6c0304758177b17d7fa786ab27a2fdb61dc5 100644 --- a/lib/modules/blockchain/blockchain/src/dbex.rs +++ b/lib/modules/blockchain/blockchain/src/dbex.rs @@ -16,6 +16,7 @@ use crate::*; use dubp_documents::documents::transaction::*; use dup_crypto::keys::*; +use durs_blockchain_dal::constants::CURRENCY_PARAMS_DB_NAME; use durs_module::DursConfTrait; use durs_wot::data::rusty::RustyWebOfTrust; use durs_wot::data::WebOfTrust; @@ -133,8 +134,9 @@ pub fn dbex_wot<DC: DursConfTrait>( // Open databases let load_dbs_begin = SystemTime::now(); - let currency_params_db = open_file_db::<CurrencyParamsV10Datas>(&db_path, "params.db") - .expect("Fail to open params db"); + let currency_params_db = + open_file_db::<CurrencyParamsV10Datas>(&db_path, CURRENCY_PARAMS_DB_NAME) + .expect("Fail to open params db"); let wot_databases = WotsV10DBs::open(Some(&db_path)); let load_dbs_duration = SystemTime::now() .duration_since(load_dbs_begin) @@ -147,8 +149,13 @@ pub fn dbex_wot<DC: DursConfTrait>( // Get currency parameters let currency_params = currency_params_db - .read(|db| CurrencyParameters::from(db.clone())) - .expect("Fail to parse currency params !"); + .read(|db| { + db.as_ref().map(|(currency_name, block_genesis_params)| { + CurrencyParameters::from((currency_name.clone(), *block_genesis_params)) + }) + }) + .expect("Fail to parse currency params !") + .unwrap_or_default(); // get wot_index let wot_index = diff --git a/lib/modules/blockchain/blockchain/src/dubp/mod.rs b/lib/modules/blockchain/blockchain/src/dubp/mod.rs index 8497532b892a704144ad47dfe633a5767f0cc624..aca84e0f2ccf55c0b52206b5d91fd803218b2c6a 100644 --- a/lib/modules/blockchain/blockchain/src/dubp/mod.rs +++ b/lib/modules/blockchain/blockchain/src/dubp/mod.rs @@ -25,17 +25,19 @@ use dubp_documents::Blockstamp; use dubp_documents::Document; use durs_blockchain_dal::entities::block::DALBlock; use durs_blockchain_dal::*; +use unwrap::unwrap; #[derive(Debug, Clone)] pub enum CheckAndApplyBlockReturn { - ValidBlock(ValidBlockApplyReqs), + ValidMainBlock(ValidBlockApplyReqs), ForkBlock, OrphanBlock, } #[derive(Debug, Copy, Clone)] pub enum BlockError { - AlreadyHaveBlockOrOutForkWindow, + AlreadyHaveBlock, + BlockOrOutForkWindow, VerifyBlockHashsError(VerifyBlockHashsError), DALError(DALError), InvalidBlock(InvalidBlockError), @@ -100,16 +102,29 @@ pub fn check_and_apply_block( &bc.wot_databases.wot_db, )?; - Ok(CheckAndApplyBlockReturn::ValidBlock(apply_valid_block( + // If we're in block genesis, get the currency parameters + if block_doc.number == BlockNumber(0) { + // Open currency_params_db + let dbs_path = durs_conf::get_blockchain_db_path(bc.profile_path.clone(), &bc.currency); + // Get and write currency params + bc.currency_params = Some( + durs_blockchain_dal::readers::currency_params::get_and_write_currency_params( + &dbs_path, &block_doc, + ), + ); + } + + Ok(CheckAndApplyBlockReturn::ValidMainBlock(apply_valid_block( block_doc, &mut bc.wot_index, &bc.wot_databases.wot_db, &expire_certs, )?)) - } else if !already_have_block - && (block_doc.number.0 >= bc.current_blockstamp.id.0 - || (bc.current_blockstamp.id.0 - block_doc.number.0) - < bc.currency_params.fork_window_size as u32) + } else if already_have_block { + Err(BlockError::AlreadyHaveBlock) + } else if block_doc.number.0 >= bc.current_blockstamp.id.0 + || (bc.current_blockstamp.id.0 - block_doc.number.0) + < unwrap!(bc.currency_params).fork_window_size as u32 { debug!( "stackable_block : block {} not chainable, store this for future !", @@ -133,6 +148,6 @@ pub fn check_and_apply_block( "stackable_block : block {} not chainable and already stored or out of forkWindowSize !", block_doc.blockstamp() ); - Err(BlockError::AlreadyHaveBlockOrOutForkWindow) + Err(BlockError::BlockOrOutForkWindow) } } diff --git a/lib/modules/blockchain/blockchain/src/dunp/queries.rs b/lib/modules/blockchain/blockchain/src/dunp/queries.rs index 3fbbb16dfa441f2a40c6f040d3974c88962d8bc7..21280d267535479200460240a172f505962c39d0 100644 --- a/lib/modules/blockchain/blockchain/src/dunp/queries.rs +++ b/lib/modules/blockchain/blockchain/src/dunp/queries.rs @@ -56,7 +56,7 @@ pub fn request_blocks_to( bc: &BlockchainModule, to: BlockNumber, ) -> HashMap<ModuleReqId, OldNetworkRequest> { - let mut from = if bc.current_blockstamp == Blockstamp::default() { + let from = if bc.current_blockstamp == Blockstamp::default() { 0 } else { bc.current_blockstamp.id.0 + 1 @@ -66,24 +66,53 @@ pub fn request_blocks_to( bc.current_blockstamp.id.0 + 1, to ); - let mut requests_ids = HashMap::new(); if bc.current_blockstamp.id < to { let real_to = if (to.0 - bc.current_blockstamp.id.0) > *MAX_BLOCKS_REQUEST { bc.current_blockstamp.id.0 + *MAX_BLOCKS_REQUEST } else { to.0 }; - while from <= real_to { - let mut req_id = ModuleReqId(0); - while bc.pending_network_requests.contains_key(&req_id) - || requests_ids.contains_key(&req_id) - { - req_id = ModuleReqId(req_id.0 + 1); - } - let (req_id, req) = request_chunk(bc, req_id, from); - requests_ids.insert(req_id, req); - from += *CHUNK_SIZE; + request_blocks_from_to(bc, from, real_to) + } else { + HashMap::with_capacity(0) + } +} + +/// Requets previous blocks from specific orphan block +#[inline] +pub fn request_orphan_previous( + _bc: &BlockchainModule, + _orphan_block_number: BlockNumber, +) -> HashMap<ModuleReqId, OldNetworkRequest> { + /*if orphan_block_number.0 + > bc.current_blockstamp.id.0 - *durs_blockchain_dal::constants::FORK_WINDOW_SIZE as u32 + && orphan_block_number.0 <= bc.current_blockstamp.id.0 + *CHUNK_SIZE + { + request_blocks_from_to( + bc, + orphan_block_number.0 - *CHUNK_SIZE + 1, + orphan_block_number.0, + ) + } else {*/ + HashMap::with_capacity(0) +} + +fn request_blocks_from_to( + bc: &BlockchainModule, + mut from: u32, + to: u32, +) -> HashMap<ModuleReqId, OldNetworkRequest> { + let mut requests_ids = HashMap::new(); + while from <= to { + let mut req_id = ModuleReqId(0); + while bc.pending_network_requests.contains_key(&req_id) + || requests_ids.contains_key(&req_id) + { + req_id = ModuleReqId(req_id.0 + 1); } + let (req_id, req) = request_chunk(bc, req_id, from); + requests_ids.insert(req_id, req); + from += *CHUNK_SIZE; } requests_ids } diff --git a/lib/modules/blockchain/blockchain/src/dunp/receiver.rs b/lib/modules/blockchain/blockchain/src/dunp/receiver.rs index 9ec45acb4facf8c510bbf011b41c496394ad9aa1..f6c141fe3b81ba2fd8d31261a842663e52e41460 100644 --- a/lib/modules/blockchain/blockchain/src/dunp/receiver.rs +++ b/lib/modules/blockchain/blockchain/src/dunp/receiver.rs @@ -18,6 +18,7 @@ use crate::*; use std::ops::Deref; +use unwrap::unwrap; pub fn receive_bc_documents(bc: &mut BlockchainModule, network_documents: &[BlockchainDocument]) { for network_document in network_documents { @@ -29,15 +30,16 @@ pub fn receive_bc_documents(bc: &mut BlockchainModule, network_documents: &[Bloc } pub fn receive_blocks(bc: &mut BlockchainModule, blocks: Vec<BlockDocument>) { - debug!("BlockchainModule : receive_blocks()"); + debug!("BlockchainModule : receive_blocks({})", blocks.len()); let mut save_blocks_dbs = false; let mut save_wots_dbs = false; let mut save_currency_dbs = false; + let mut first_orphan = true; for block in blocks.into_iter() { let blockstamp = block.blockstamp(); match check_and_apply_block(bc, block) { Ok(check_block_return) => match check_block_return { - CheckAndApplyBlockReturn::ValidBlock(ValidBlockApplyReqs( + CheckAndApplyBlockReturn::ValidMainBlock(ValidBlockApplyReqs( bc_db_query, wot_dbs_queries, tx_dbs_queries, @@ -49,13 +51,13 @@ pub fn receive_blocks(bc: &mut BlockchainModule, blocks: Vec<BlockDocument>) { .apply( &bc.blocks_databases.blockchain_db, &bc.forks_dbs, - bc.currency_params.fork_window_size, + unwrap!(bc.currency_params).fork_window_size, None, ) .expect("Fatal error : Fail to apply DBWriteRequest !"); for query in &wot_dbs_queries { query - .apply(&blockstamp, &bc.currency_params, &bc.wot_databases) + .apply(&blockstamp, &unwrap!(bc.currency_params), &bc.wot_databases) .expect("Fatal error : Fail to apply WotsDBsWriteRequest !"); } for query in &tx_dbs_queries { @@ -76,10 +78,10 @@ pub fn receive_blocks(bc: &mut BlockchainModule, blocks: Vec<BlockDocument>) { ); } CheckAndApplyBlockReturn::ForkBlock => { - info!("new fork block({})", blockstamp); + info!("new fork block(#{})", blockstamp); if let Ok(Some(new_bc_branch)) = fork_algo::fork_resolution_algo( &bc.forks_dbs, - bc.currency_params.fork_window_size, + unwrap!(bc.currency_params).fork_window_size, bc.current_blockstamp, &bc.invalid_forks, ) { @@ -87,24 +89,31 @@ pub fn receive_blocks(bc: &mut BlockchainModule, blocks: Vec<BlockDocument>) { } } CheckAndApplyBlockReturn::OrphanBlock => { - debug!("new orphan block({})", blockstamp); + if first_orphan { + first_orphan = false; + info!("new orphan block(#{})", blockstamp); // TODO debug + crate::requests::sent::request_orphan_previous(bc, blockstamp); + } } }, Err(e) => match e { BlockError::VerifyBlockHashsError(_) | BlockError::InvalidBlock(_) => { - warn!("InvalidBlock({})", blockstamp.id.0); + warn!("InvalidBlock(#{})", blockstamp.id.0); crate::events::sent::send_event(bc, &BlockchainEvent::RefusedBlock(blockstamp)); } BlockError::ApplyValidBlockError(e2) => { - error!("ApplyValidBlockError({}): {:?}", blockstamp.id.0, e2); + error!("ApplyValidBlockError(#{}): {:?}", blockstamp, e2); crate::events::sent::send_event(bc, &BlockchainEvent::RefusedBlock(blockstamp)); } BlockError::DALError(e2) => { - error!("BlockError::DALError({}): {:?}", blockstamp.id.0, e2); + error!("BlockError::DALError(#{}): {:?}", blockstamp, e2); crate::events::sent::send_event(bc, &BlockchainEvent::RefusedBlock(blockstamp)); } - BlockError::AlreadyHaveBlockOrOutForkWindow => { - debug!("AlreadyHaveBlockOrOutForkWindow({})", blockstamp.id.0); + BlockError::AlreadyHaveBlock => { + debug!("AlreadyHaveBlock(#{})", blockstamp.id); + } + BlockError::BlockOrOutForkWindow => { + info!("BlockOrOutForkWindow(#{})", blockstamp); // TODO debug } }, } diff --git a/lib/modules/blockchain/blockchain/src/fork/rollback.rs b/lib/modules/blockchain/blockchain/src/fork/rollback.rs index 7cacbe9d2c6bc7dc343e558839aef4bf48d45351..8d4eab35523f2ead00711fcff3c96cfffbc5628a 100644 --- a/lib/modules/blockchain/blockchain/src/fork/rollback.rs +++ b/lib/modules/blockchain/blockchain/src/fork/rollback.rs @@ -17,6 +17,7 @@ use crate::fork::revert_block::ValidBlockRevertReqs; use crate::*; use dubp_documents::Blockstamp; use durs_common_tools::fatal_error; +use unwrap::unwrap; pub fn apply_rollback(bc: &mut BlockchainModule, new_bc_branch: Vec<Blockstamp>) { if new_bc_branch.is_empty() { @@ -52,13 +53,13 @@ pub fn apply_rollback(bc: &mut BlockchainModule, new_bc_branch: Vec<Blockstamp>) .apply( &bc.blocks_databases.blockchain_db, &bc.forks_dbs, - bc.currency_params.fork_window_size, + unwrap!(bc.currency_params).fork_window_size, None, ) .expect("Fatal error : Fail to apply DBWriteRequest !"); for query in &wot_dbs_queries { query - .apply(&blockstamp, &bc.currency_params, &bc.wot_databases) + .apply(&blockstamp, &unwrap!(bc.currency_params), &bc.wot_databases) .expect("Fatal error : Fail to apply WotsDBsWriteRequest !"); } for query in &tx_dbs_queries { @@ -79,7 +80,7 @@ pub fn apply_rollback(bc: &mut BlockchainModule, new_bc_branch: Vec<Blockstamp>) .fork_blocks_db .read(|db| db.get(&blockstamp).cloned()) { - if let Ok(CheckAndApplyBlockReturn::ValidBlock(ValidBlockApplyReqs( + if let Ok(CheckAndApplyBlockReturn::ValidMainBlock(ValidBlockApplyReqs( bc_db_query, wot_dbs_queries, tx_dbs_queries, @@ -91,13 +92,13 @@ pub fn apply_rollback(bc: &mut BlockchainModule, new_bc_branch: Vec<Blockstamp>) .apply( &bc.blocks_databases.blockchain_db, &bc.forks_dbs, - bc.currency_params.fork_window_size, + unwrap!(bc.currency_params).fork_window_size, None, ) .expect("Fatal error : Fail to apply DBWriteRequest !"); for query in &wot_dbs_queries { query - .apply(&blockstamp, &bc.currency_params, &bc.wot_databases) + .apply(&blockstamp, &unwrap!(bc.currency_params), &bc.wot_databases) .expect("Fatal error : Fail to apply WotsDBsWriteRequest !"); } for query in &tx_dbs_queries { diff --git a/lib/modules/blockchain/blockchain/src/fork/stackable_blocks.rs b/lib/modules/blockchain/blockchain/src/fork/stackable_blocks.rs index 9a4ca491d404c5e23cc170f165c365fee1ee1026..f6aeaf8a8fb1f3908ec0ecb4926494a505781800 100644 --- a/lib/modules/blockchain/blockchain/src/fork/stackable_blocks.rs +++ b/lib/modules/blockchain/blockchain/src/fork/stackable_blocks.rs @@ -16,6 +16,7 @@ //! Sub-module that finds and applies the orphaned blocks that have become stackable on the local blockchain. use crate::*; +use unwrap::unwrap; pub fn apply_stackable_blocks(bc: &mut BlockchainModule) { 'blockchain: loop { @@ -33,7 +34,7 @@ pub fn apply_stackable_blocks(bc: &mut BlockchainModule) { let stackable_block_number = stackable_block.block.number; let stackable_block_blockstamp = stackable_block.block.blockstamp(); - if let Ok(CheckAndApplyBlockReturn::ValidBlock(ValidBlockApplyReqs( + if let Ok(CheckAndApplyBlockReturn::ValidMainBlock(ValidBlockApplyReqs( bc_db_query, wot_dbs_queries, tx_dbs_queries, @@ -46,13 +47,13 @@ pub fn apply_stackable_blocks(bc: &mut BlockchainModule) { .apply( &bc.blocks_databases.blockchain_db, &bc.forks_dbs, - bc.currency_params.fork_window_size, + unwrap!(bc.currency_params).fork_window_size, None, ) .expect("Fatal error : Fail to apply DBWriteRequest !"); for query in &wot_dbs_queries { query - .apply(&blockstamp, &bc.currency_params, &bc.wot_databases) + .apply(&blockstamp, &unwrap!(bc.currency_params), &bc.wot_databases) .expect("Fatal error : Fail to apply WotsDBsWriteRequest !"); } for query in &tx_dbs_queries { diff --git a/lib/modules/blockchain/blockchain/src/lib.rs b/lib/modules/blockchain/blockchain/src/lib.rs index 64d05dc4b0a90b67497c86aaa04e7b2cf1a19fad..89a9616e47558563b3d0379e1e13f3746a08f84e 100644 --- a/lib/modules/blockchain/blockchain/src/lib.rs +++ b/lib/modules/blockchain/blockchain/src/lib.rs @@ -104,7 +104,7 @@ pub struct BlockchainModule { /// Currency databases currency_databases: CurrencyV10DBs, /// Currency parameters - pub currency_params: CurrencyParameters, + pub currency_params: Option<CurrencyParameters>, /// Current blockstamp pub current_blockstamp: Blockstamp, /// network consensus blockstamp @@ -115,6 +115,8 @@ pub struct BlockchainModule { pub invalid_forks: HashSet<Blockstamp>, /// pending network requests pub pending_network_requests: HashMap<ModuleReqId, OldNetworkRequest>, + /// Last request blocks + pub last_request_blocks: SystemTime, } #[derive(Debug, Clone)] @@ -206,11 +208,9 @@ impl BlockchainModule { .unwrap_or_default(); // Get currency parameters - let currency_params = durs_blockchain_dal::readers::currency_params::get_currency_params( - &blocks_databases.blockchain_db, - ) - .expect("Fatal error : fail to read Blockchain DB !") - .unwrap_or_default(); + let currency_params = + durs_blockchain_dal::readers::currency_params::get_currency_params(&dbs_path) + .expect("Fatal error : fail to read Blockchain DB !"); // Get wot index let wot_index: HashMap<PubKey, NodeId> = @@ -233,6 +233,7 @@ impl BlockchainModule { pending_block: None, invalid_forks: HashSet::new(), pending_network_requests: HashMap::new(), + last_request_blocks: UNIX_EPOCH, } } /// Databases explorer @@ -251,6 +252,11 @@ impl BlockchainModule { ) { info!("BlockchainModule::start_blockchain()"); + // Send currency parameters to other modules + if let Some(currency_params) = self.currency_params { + events::sent::send_event(self, &BlockchainEvent::CurrencyParameters(currency_params)); + } + if let Some(_sync_opts) = sync_opts { // TODO ... } else { @@ -263,22 +269,12 @@ impl BlockchainModule { pub fn main_loop(&mut self, blockchain_receiver: &mpsc::Receiver<DursMsg>) { // Init main loop datas let mut last_get_stackables_blocks = UNIX_EPOCH; - let mut last_request_blocks = UNIX_EPOCH; loop { // Request Consensus requests::sent::request_network_consensus(self); - // Request next main blocks every 20 seconds - let now = SystemTime::now(); - if now - .duration_since(last_request_blocks) - .expect("duration_since error") - > Duration::new(20, 0) - { - last_request_blocks = now; - // Request next main blocks - requests::sent::request_next_main_blocks(self); - } + // Request next main blocks + requests::sent::request_next_main_blocks(self); match blockchain_receiver.recv_timeout(Duration::from_millis(1000)) { Ok(durs_message) => { match durs_message { diff --git a/lib/modules/blockchain/blockchain/src/requests/sent.rs b/lib/modules/blockchain/blockchain/src/requests/sent.rs index 1e0f2a1288caae3bf30dd4ab2b1af27ee9e2fd0d..779b22d9e386c2a3e258956fd192e849786a44f4 100644 --- a/lib/modules/blockchain/blockchain/src/requests/sent.rs +++ b/lib/modules/blockchain/blockchain/src/requests/sent.rs @@ -31,13 +31,40 @@ pub fn request_network_consensus(bc: &mut BlockchainModule) { bc.pending_network_requests.insert(req_id, req); } -pub fn request_next_main_blocks(bc: &mut BlockchainModule) { - let to = match bc.consensus.id.0 { - 0 => (bc.current_blockstamp.id.0 + *MAX_BLOCKS_REQUEST), - _ => bc.consensus.id.0, - }; - let new_pending_network_requests = dunp::queries::request_blocks_to(bc, BlockNumber(to)); +pub fn request_orphan_previous(bc: &mut BlockchainModule, orphan_blockstamp: Blockstamp) { + let new_pending_network_requests = + dunp::queries::request_orphan_previous(bc, orphan_blockstamp.id); for (new_req_id, new_req) in new_pending_network_requests { bc.pending_network_requests.insert(new_req_id, new_req); } } + +pub fn request_next_main_blocks(bc: &mut BlockchainModule) { + // Choose frequency + let frequency = if bc.consensus.id.0 == 0 + || bc.consensus.id.0 > bc.current_blockstamp.id.0 + *BLOCKS_DELAY_THRESHOLD + { + *REQUEST_MAIN_BLOCKS_HIGH_FREQUENCY_IN_SEC + } else { + *REQUEST_MAIN_BLOCKS_LOW_FREQUENCY_IN_SEC + }; + + // Apply frequency + let now = SystemTime::now(); + if now + .duration_since(bc.last_request_blocks) + .expect("duration_since error") + > Duration::from_secs(frequency) + { + bc.last_request_blocks = now; + // Request next main blocks + let to = match bc.consensus.id.0 { + 0 => (bc.current_blockstamp.id.0 + *MAX_BLOCKS_REQUEST), + _ => bc.consensus.id.0, + }; + let new_pending_network_requests = dunp::queries::request_blocks_to(bc, BlockNumber(to)); + for (new_req_id, new_req) in new_pending_network_requests { + bc.pending_network_requests.insert(new_req_id, new_req); + } + } +} diff --git a/lib/modules/blockchain/blockchain/src/sync/mod.rs b/lib/modules/blockchain/blockchain/src/sync/mod.rs index 78da0a69020fffd712f63b74614e19a4c9334210..03bd0874a1e0b83dc825ac20898b11ca998b5423 100644 --- a/lib/modules/blockchain/blockchain/src/sync/mod.rs +++ b/lib/modules/blockchain/blockchain/src/sync/mod.rs @@ -84,26 +84,6 @@ fn get_json_files_path(source: Option<String>, currency: Option<String>) -> Path } } -/// Get and write currency params -fn get_and_write_currency_params( - currency_params_db: &BinDB<CurrencyParamsV10Datas>, - block_doc: &BlockDocument, -) -> CurrencyParameters { - if block_doc.number.0 != 0 { - fatal_error!("The first block must have number equal to zero !"); - } else if block_doc.parameters.is_none() { - fatal_error!("The genesis block must have parameters !"); - } else { - currency_params_db - .write(|db| { - db.0 = block_doc.currency.clone(); - db.1 = block_doc.parameters.unwrap(); - }) - .expect("fail to write in params DB"); - CurrencyParameters::from((block_doc.currency.clone(), block_doc.parameters.unwrap())) - } -} - /// Sync from local json files pub fn local_sync<DC: DursConfTrait>(profile_path: PathBuf, conf: &DC, sync_opts: SyncOpt) { let SyncOpt { @@ -272,10 +252,6 @@ pub fn local_sync<DC: DursConfTrait>(profile_path: PathBuf, conf: &DC, sync_opts // Open currency_params_db let dbs_path = durs_conf::get_blockchain_db_path(profile_path, &conf.currency()); - let currency_params_db = BinDB::File( - open_file_db::<CurrencyParamsV10Datas>(&dbs_path, "params.db") - .expect("Fail to open params db"), - ); // Apply blocks let mut blocks_not_expiring = VecDeque::with_capacity(200_000); @@ -303,7 +279,23 @@ pub fn local_sync<DC: DursConfTrait>(profile_path: PathBuf, conf: &DC, sync_opts .unwrap(); // Get and write currency params if !get_currency_params { - currency_params = get_and_write_currency_params(¤cy_params_db, &block_doc); + if block_doc.number == BlockNumber(0) { + currency_params = + durs_blockchain_dal::readers::currency_params::get_and_write_currency_params( + &dbs_path, &block_doc, + ); + } else { + currency_params = + match durs_blockchain_dal::readers::currency_params::get_currency_params( + &dbs_path, + ) { + Ok(Some(currency_params)) => currency_params, + Ok(None) => { + fatal_error!("Params db corrupted: please reset data and resync !") + } + Err(_) => fatal_error!("Fail to open params db"), + } + } get_currency_params = true; } // Push block median_time in blocks_not_expiring @@ -417,9 +409,6 @@ pub fn local_sync<DC: DursConfTrait>(profile_path: PathBuf, conf: &DC, sync_opts .expect("Sync : Fail to send End signal to writer worker !"); info!("Sync : send End signal to tx job."); - // Save params db - currency_params_db.save().expect("Fail to save params db"); - // Save wot db wot_databases.wot_db.save().expect("Fail to save wot db"); diff --git a/lib/modules/ws2p-v1-legacy/src/lib.rs b/lib/modules/ws2p-v1-legacy/src/lib.rs index 79076ccac19b8f39f6366dbe7c39da1339ab31c3..c6ede1f282790215bb5b2ff0e025cc731fc3b150 100644 --- a/lib/modules/ws2p-v1-legacy/src/lib.rs +++ b/lib/modules/ws2p-v1-legacy/src/lib.rs @@ -562,6 +562,7 @@ impl DursModule<DuRsConf, DursMsg> for WS2Pv1Module { sender: proxy_sender_clone, roles: vec![ModuleRole::InterNodesNetwork], events_subscription: vec![ + ModuleEvent::CurrencyParameters, ModuleEvent::NewValidBlock, ModuleEvent::NewWotDocInPool, ModuleEvent::NewTxinPool,