Skip to content
Snippets Groups Projects
Commit 7150e7d8 authored by Éloïs's avatar Éloïs
Browse files

[fix] whole: currency-params must be optional

parent fce5a376
No related branches found
No related tags found
1 merge request!165[fix] whole: currency-params must be optional
Showing
with 173 additions and 81 deletions
......@@ -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",
......
......@@ -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";
......@@ -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(&currency.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::*;
......
......@@ -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
......
......@@ -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" }
......
......@@ -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
......
File moved
File moved
File moved
......@@ -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,
......
......@@ -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]
......@@ -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";
......@@ -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)
......
......@@ -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 !");
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 {
None
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),
))
}
})?)
}
......@@ -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" }
......
cyclomatic-complexity-threshold = 42
cyclomatic-complexity-threshold = 46
too-many-arguments-threshold = 8
\ No newline at end of file
......@@ -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;
......@@ -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,7 +134,8 @@ 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")
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()
......@@ -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 =
......
......@@ -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
} 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)
< bc.currency_params.fork_window_size as u32)
< 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)
}
}
......@@ -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,14 +66,44 @@ 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 {
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)
......@@ -84,6 +114,5 @@ pub fn request_blocks_to(
requests_ids.insert(req_id, req);
from += *CHUNK_SIZE;
}
}
requests_ids
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment