diff --git a/lib/modules/blockchain/blockchain-dal/Cargo.toml b/lib/modules/blockchain/blockchain-dal/Cargo.toml index bfc3feb41723d63cd51992dcf2e353aa2f931070..332f49eb8ed989cbb773bb8e60c8acc02484a920 100644 --- a/lib/modules/blockchain/blockchain-dal/Cargo.toml +++ b/lib/modules/blockchain/blockchain-dal/Cargo.toml @@ -7,7 +7,7 @@ license = "AGPL-3.0" edition = "2018" [lib] -path = "lib.rs" +path = "src/lib.rs" [dependencies] dup-crypto = { path = "../../../tools/crypto" } diff --git a/lib/modules/blockchain/blockchain-dal/block.rs b/lib/modules/blockchain/blockchain-dal/block.rs deleted file mode 100644 index c6e95e05bdfd16e805fbbb7e5bee789d969b95d8..0000000000000000000000000000000000000000 --- a/lib/modules/blockchain/blockchain-dal/block.rs +++ /dev/null @@ -1,407 +0,0 @@ -// 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/>. - -use super::constants::MAX_FORKS; -use crate::*; -use dubp_documents::documents::block::BlockDocument; -use dubp_documents::Document; -use dubp_documents::{BlockHash, BlockId, Blockstamp, PreviousBlockstamp}; -use dup_crypto::keys::*; -use durs_wot::NodeId; -use std::collections::HashMap; - -#[derive(Clone, Debug, Deserialize, Serialize)] -/// A block as it is saved in a database -pub struct DALBlock { - /// Fork id - pub fork_id: ForkId, - /// True only if the block is on an isolated fork - pub isolate: bool, - /// Block document - pub block: BlockDocument, - /// List of certifications that expire in this block. - /// Warning : BlockId contain the emission block, not the written block ! - /// HashMap<(Source, Target), CreatedBlockId> - pub expire_certs: Option<HashMap<(NodeId, NodeId), BlockId>>, -} - -impl DALBlock { - /// Get blockstamp - pub fn blockstamp(&self) -> Blockstamp { - self.block.blockstamp() - } -} - -///Get forks status -pub fn get_forks( - forks_db: &BinDB<ForksV10Datas>, - current_blockstamp: Blockstamp, -) -> Result<Vec<ForkStatus>, DALError> { - Ok(forks_db.read(|forks_db| { - let blockchain_meta_datas = forks_db - .get(&ForkId(0)) - .expect("Fatal error : ForksV10DB not contain local chain !"); - let mut forks = Vec::new(); - for fork_id in 1..*MAX_FORKS { - if let Some(fork_meta_datas) = forks_db.get(&ForkId(fork_id)) { - if fork_meta_datas.is_empty() { - forks.push(ForkStatus::Free()); - } else if fork_meta_datas.contains_key(¤t_blockstamp) { - forks.push(ForkStatus::Stackable(ForkAlreadyCheck(false))); - } else { - let roll_back_max = if current_blockstamp.id.0 > 101 { - current_blockstamp.id.0 - 101 - } else { - 0 - }; - let mut max_common_block_id = None; - let mut too_old = false; - for previous_blockstamp in fork_meta_datas.keys() { - if blockchain_meta_datas.contains_key(&previous_blockstamp) { - if previous_blockstamp.id.0 >= roll_back_max { - if previous_blockstamp.id.0 - >= max_common_block_id.unwrap_or(BlockId(0)).0 - { - max_common_block_id = Some(previous_blockstamp.id); - too_old = false; - } - } else { - too_old = true; - } - } - } - if too_old { - forks.push(ForkStatus::TooOld(ForkAlreadyCheck(false))); - } else if let Some(max_common_block_id) = max_common_block_id { - forks.push(ForkStatus::RollBack( - ForkAlreadyCheck(false), - max_common_block_id, - )); - } else { - forks.push(ForkStatus::Isolate()); - } - } - } else { - forks.push(ForkStatus::Free()); - } - } - forks - })?) -} -/// get current blockstamp -pub fn get_current_blockstamp(blocks_db: &BlocksV10DBs) -> Result<Option<Blockstamp>, DALError> { - let current_previous_blockstamp = blocks_db.blockchain_db.read(|db| { - let blockchain_len = db.len() as u32; - if blockchain_len == 0 { - None - } else if let Some(dal_block) = db.get(&BlockId(blockchain_len - 1)) { - if blockchain_len > 1 { - Some(Blockstamp { - id: BlockId(blockchain_len - 2), - hash: BlockHash(dal_block.block.previous_hash), - }) - } else { - Some(Blockstamp::default()) - } - } else { - None - } - })?; - if current_previous_blockstamp.is_none() { - return Ok(None); - } - let current_previous_blockstamp = current_previous_blockstamp.expect("safe unwrap"); - if let Some(current_block_hash) = blocks_db.forks_db.read(|db| { - let blockchain_meta_datas = db - .get(&ForkId(0)) - .expect("Fatal error : ForksDB is incoherent, please reset data and resync !"); - blockchain_meta_datas - .get(¤t_previous_blockstamp) - .cloned() - })? { - Ok(Some(Blockstamp { - id: BlockId(current_previous_blockstamp.id.0 + 1), - hash: current_block_hash, - })) - } else { - Ok(None) - } -} - -/// Get block fork id -pub fn get_fork_id_of_blockstamp( - forks_blocks_db: &BinDB<ForksBlocksV10Datas>, - blockstamp: &Blockstamp, -) -> Result<Option<ForkId>, DALError> { - Ok(forks_blocks_db.read(|db| { - if let Some(dal_block) = db.get(blockstamp) { - Some(dal_block.fork_id) - } else { - None - } - })?) -} - -impl DALBlock { - /// Delete fork - pub fn delete_fork( - forks_db: &BinDB<ForksV10Datas>, - forks_blocks_db: &BinDB<ForksBlocksV10Datas>, - fork_id: ForkId, - ) -> Result<(), DALError> { - let fork_meta_datas = forks_db - .read(|forks_db| forks_db.get(&fork_id).cloned())? - .expect("Fatal error : try to delete unknow fork"); - // Remove fork blocks - forks_blocks_db.write(|db| { - for (previous_blockstamp, hash) in fork_meta_datas { - let blockstamp = Blockstamp { - id: BlockId(previous_blockstamp.id.0 + 1), - hash, - }; - db.remove(&blockstamp); - } - })?; - // Remove fork meta datas - forks_db.write_safe(|db| { - db.remove(&fork_id); - })?; - Ok(()) - } - /// Assign fork id to new block - pub fn assign_fork_to_new_block( - forks_db: &BinDB<ForksV10Datas>, - new_block_previous_blockstamp: &PreviousBlockstamp, - new_block_hash: &BlockHash, - ) -> Result<(Option<ForkId>, bool), DALError> { - let forks_meta_datas = forks_db.read(|forks_db| forks_db.clone())?; - // Try to assign block to an existing fork - for (fork_id, fork_meta_datas) in &forks_meta_datas { - let mut fork_datas = fork_meta_datas.clone(); - for (previous_blockstamp, hash) in fork_meta_datas { - let blockstamp = Blockstamp { - id: BlockId(previous_blockstamp.id.0 + 1), - hash: *hash, - }; - if *new_block_previous_blockstamp == blockstamp { - fork_datas.insert(*new_block_previous_blockstamp, *new_block_hash); - forks_db.write(|forks_db| { - forks_db.insert(*fork_id, fork_datas); - })?; - return Ok((Some(*fork_id), false)); - } - } - } - // Find an available fork - let mut new_fork_id = ForkId(0); - for f in 0..*MAX_FORKS { - if !forks_meta_datas.contains_key(&ForkId(f)) { - new_fork_id = ForkId(f); - break; - } - } - if new_fork_id.0 == 0 { - if forks_meta_datas.len() >= *MAX_FORKS { - return Ok((None, false)); - } else { - new_fork_id = ForkId(forks_meta_datas.len()); - } - } - // Create new fork - let mut new_fork = HashMap::new(); - new_fork.insert(*new_block_previous_blockstamp, *new_block_hash); - forks_db.write(|forks_db| { - forks_db.insert(new_fork_id, new_fork); - })?; - Ok((Some(new_fork_id), true)) - } - /// Get fork block - pub fn get_block_fork( - forks_db: &BinDB<ForksV10Datas>, - previous_blockstamp: &PreviousBlockstamp, - ) -> Result<Option<ForkId>, DALError> { - Ok(forks_db.read(|forks_db| { - for (fork_id, fork_meta_datas) in forks_db { - if fork_meta_datas.contains_key(&previous_blockstamp) { - return Some(*fork_id); - } - } - None - })?) - } - /// Get block hash - pub fn get_block_hash( - db: &BinDB<LocalBlockchainV10Datas>, - block_number: BlockId, - ) -> Result<Option<BlockHash>, DALError> { - Ok(db.read(|db| { - if let Some(dal_block) = db.get(&block_number) { - dal_block.block.hash - } else { - None - } - })?) - } - /// Return true if the node already knows this block - pub fn already_have_block( - blockchain_db: &BinDB<LocalBlockchainV10Datas>, - forks_blocks_db: &BinDB<ForksBlocksV10Datas>, - blockstamp: Blockstamp, - ) -> Result<bool, DALError> { - let already_have_block = forks_blocks_db.read(|db| db.contains_key(&blockstamp))?; - if !already_have_block { - Ok(blockchain_db.read(|db| { - if let Some(dal_block) = db.get(&blockstamp.id) { - if dal_block.block.hash.unwrap_or_default() == blockstamp.hash { - return true; - } - } - false - })?) - } else { - Ok(true) - } - } - /// Get stackables blocks - pub fn get_stackables_blocks( - forks_db: &BinDB<ForksV10Datas>, - forks_blocks_db: &BinDB<ForksBlocksV10Datas>, - current_blockstamp: &Blockstamp, - ) -> Result<Vec<DALBlock>, DALError> { - debug!("get_stackables_blocks() after {}", current_blockstamp); - let stackables_blocks_hashs = forks_db.read(|db| { - let mut stackables_blocks_hashs = Vec::new(); - for fork_meta_datas in db.values() { - if let Some(block_hash) = fork_meta_datas.get(¤t_blockstamp) { - stackables_blocks_hashs.push(*block_hash); - } - } - stackables_blocks_hashs - })?; - let stackables_blocks = forks_blocks_db.read(|db| { - let mut stackables_blocks = Vec::new(); - for stackable_block_hash in stackables_blocks_hashs { - if let Some(dal_block) = db.get(&Blockstamp { - id: BlockId(current_blockstamp.id.0 + 1), - hash: stackable_block_hash, - }) { - stackables_blocks.push(dal_block.clone()); - } - } - stackables_blocks - })?; - Ok(stackables_blocks) - } - /// Get stackables forks - pub fn get_stackables_forks( - db: &BinDB<ForksV10Datas>, - current_blockstamp: &Blockstamp, - ) -> Result<Vec<usize>, DALError> { - Ok(db.read(|db| { - let mut stackables_forks = Vec::new(); - for f in 0..*MAX_FORKS { - if let Some(fork_meta_datas) = db.get(&ForkId(f)) { - if fork_meta_datas.get(¤t_blockstamp).is_some() { - stackables_forks.push(f); - } - } - } - stackables_forks - })?) - } - /// Get block - pub fn get_block( - blockchain_db: &BinDB<LocalBlockchainV10Datas>, - forks_blocks_db: Option<&BinDB<ForksBlocksV10Datas>>, - blockstamp: &Blockstamp, - ) -> Result<Option<DALBlock>, DALError> { - let dal_block = blockchain_db.read(|db| db.get(&blockstamp.id).cloned())?; - if dal_block.is_none() && forks_blocks_db.is_some() { - Ok(forks_blocks_db - .expect("safe unwrap") - .read(|db| db.get(&blockstamp).cloned())?) - } else { - Ok(dal_block) - } - } - /// Get block in local blockchain - pub fn get_block_in_local_blockchain( - db: &BinDB<LocalBlockchainV10Datas>, - block_id: BlockId, - ) -> Result<Option<BlockDocument>, DALError> { - Ok(db.read(|db| { - if let Some(dal_block) = db.get(&block_id) { - Some(dal_block.block.clone()) - } else { - None - } - })?) - } - /// Get current frame of calculating members - pub fn get_current_frame( - &self, - db: &BinDB<LocalBlockchainV10Datas>, - ) -> Result<HashMap<PubKey, usize>, DALError> { - let frame_begin = self.block.number.0 - self.block.issuers_frame as u32; - Ok(db.read(|db| { - let mut current_frame: HashMap<PubKey, usize> = HashMap::new(); - for block_number in frame_begin..self.block.number.0 { - let issuer = db - .get(&BlockId(block_number)) - .unwrap_or_else(|| panic!("Fail to get block #{} !", block_number)) - .block - .issuers()[0]; - let issuer_count_blocks = - if let Some(issuer_count_blocks) = current_frame.get(&issuer) { - issuer_count_blocks + 1 - } else { - 1 - }; - current_frame.insert(issuer, issuer_count_blocks); - } - current_frame - })?) - } - /// Compute median issuers frame - pub fn compute_median_issuers_frame(&mut self, db: &BinDB<LocalBlockchainV10Datas>) { - let current_frame = self - .get_current_frame(db) - .expect("Fatal error : fail to read LocalBlockchainV10DB !"); - if !current_frame.is_empty() { - let mut current_frame_vec: Vec<_> = current_frame.values().cloned().collect(); - current_frame_vec.sort_unstable(); - - /*// Calculate median - let mut median_index = match self.block.issuers_count % 2 { - 1 => (self.block.issuers_count / 2) + 1, - _ => self.block.issuers_count / 2, - }; - if median_index >= self.block.issuers_count { - 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, - _ => (self.block.issuers_count as f64 * (2.0 / 3.0)) as usize, - }; - if second_tiercile_index >= self.block.issuers_count { - second_tiercile_index = self.block.issuers_count - 1; - } - self.second_tiercile_frame = current_frame_vec[second_tiercile_index];*/ - } - } -} diff --git a/lib/modules/blockchain/blockchain-dal/identity.rs b/lib/modules/blockchain/blockchain-dal/identity.rs deleted file mode 100644 index 7cdb0132d28fac3fd1cc4ddb22a797b5e98b1252..0000000000000000000000000000000000000000 --- a/lib/modules/blockchain/blockchain-dal/identity.rs +++ /dev/null @@ -1,282 +0,0 @@ -// 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/>. - -use crate::currency_params::CurrencyParameters; -use crate::{BinDB, DALError, IdentitiesV10Datas, MsExpirV10Datas}; -use dubp_documents::documents::identity::IdentityDocument; -use dubp_documents::{BlockId, Blockstamp}; -use dup_crypto::keys::*; -use durs_wot::NodeId; -use std::collections::HashMap; - -#[derive(Clone, Debug, Deserialize, Serialize)] -/// Identity state -pub enum DALIdentityState { - /// Member - Member(Vec<usize>), - /// Expire Member - ExpireMember(Vec<usize>), - /// Explicit Revoked - ExplicitRevoked(Vec<usize>), - /// Explicit Revoked after expire - ExplicitExpireRevoked(Vec<usize>), - /// Implicit revoked - ImplicitRevoked(Vec<usize>), -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -/// Identity in database -pub struct DALIdentity { - /// Identity hash - pub hash: String, - /// Identity state - pub state: DALIdentityState, - /// Blockstamp the identity was written - pub joined_on: Blockstamp, - /// Blockstamp the identity was expired - pub expired_on: Option<Blockstamp>, - /// Blockstamp the identity was revoked - pub revoked_on: Option<Blockstamp>, - /// Identity document - pub idty_doc: IdentityDocument, - /// Identity wot id - pub wot_id: NodeId, - /// Membership created block number - pub ms_created_block_id: BlockId, - /// Timestamp from which membership can be renewed - pub ms_chainable_on: Vec<u64>, - /// Timestamp from which the identity can write a new certification - pub cert_chainable_on: Vec<u64>, -} - -/// Get uid from pubkey -pub fn get_uid( - identities_db: &BinDB<IdentitiesV10Datas>, - pubkey: PubKey, -) -> Result<Option<String>, DALError> { - Ok(identities_db.read(|db| { - if let Some(dal_idty) = db.get(&pubkey) { - Some(String::from(dal_idty.idty_doc.username())) - } else { - None - } - })?) -} - -/// Get pubkey from uid -pub fn get_pubkey_from_uid( - identities_db: &BinDB<IdentitiesV10Datas>, - uid: &str, -) -> Result<Option<PubKey>, DALError> { - Ok(identities_db.read(|db| { - for (pubkey, dal_idty) in db { - if uid == dal_idty.idty_doc.username() { - return Some(*pubkey); - } - } - None - })?) -} - -impl DALIdentity { - /// Apply "exclude identity" event - pub fn exclude_identity( - identities_db: &BinDB<IdentitiesV10Datas>, - pubkey: &PubKey, - exclusion_blockstamp: &Blockstamp, - revert: bool, - ) -> Result<(), DALError> { - let mut idty_datas = identities_db - .read(|db| db.get(pubkey).cloned())? - .expect("Fatal error : try to renewal unknow identity !"); - idty_datas.state = if revert { - match idty_datas.state { - DALIdentityState::ExpireMember(renewed_counts) => { - DALIdentityState::Member(renewed_counts) - } - _ => panic!("Try to revert exclusion for a no excluded identity !"), - } - } else { - match idty_datas.state { - DALIdentityState::Member(renewed_counts) => { - DALIdentityState::ExpireMember(renewed_counts) - } - _ => panic!("Try to exclude for an already excluded/revoked identity !"), - } - }; - idty_datas.expired_on = if revert { - None - } else { - Some(*exclusion_blockstamp) - }; - // Write new identity datas - identities_db.write(|db| { - db.insert(*pubkey, idty_datas); - })?; - Ok(()) - } - - /// Get wot_id index - pub fn get_wot_index( - identities_db: &BinDB<IdentitiesV10Datas>, - ) -> Result<HashMap<PubKey, NodeId>, DALError> { - Ok(identities_db.read(|db| { - let mut wot_index: HashMap<PubKey, NodeId> = HashMap::new(); - for (pubkey, member_datas) in db { - let wot_id = member_datas.wot_id; - wot_index.insert(*pubkey, wot_id); - } - wot_index - })?) - } - - /// Apply "revoke identity" event - pub fn revoke_identity( - identities_db: &BinDB<IdentitiesV10Datas>, - pubkey: &PubKey, - renewal_blockstamp: &Blockstamp, - explicit: bool, - revert: bool, - ) -> Result<(), DALError> { - let mut member_datas = identities_db - .read(|db| db.get(pubkey).cloned())? - .expect("Fatal error : Try to revoke unknow idty !"); - - member_datas.state = if revert { - match member_datas.state { - DALIdentityState::ExplicitRevoked(renewed_counts) => { - DALIdentityState::Member(renewed_counts) - } - DALIdentityState::ExplicitExpireRevoked(renewed_counts) - | DALIdentityState::ImplicitRevoked(renewed_counts) => { - DALIdentityState::ExpireMember(renewed_counts) - } - _ => panic!("Try to revert revoke_identity() for a no revoked idty !"), - } - } else { - match member_datas.state { - DALIdentityState::ExpireMember(renewed_counts) => { - DALIdentityState::ExplicitExpireRevoked(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 !"), - } - }; - member_datas.revoked_on = if revert { - None - } else { - Some(*renewal_blockstamp) - }; - - identities_db.write(|db| { - db.insert(*pubkey, member_datas); - })?; - Ok(()) - } - - /// Apply "renewal identity" event in databases - pub fn renewal_identity( - &mut self, - currency_params: &CurrencyParameters, - identities_db: &BinDB<IdentitiesV10Datas>, - ms_db: &BinDB<MsExpirV10Datas>, - pubkey: &PubKey, - idty_wot_id: NodeId, - renewal_timestamp: u64, - ms_created_block_id: BlockId, - revert: bool, - ) -> Result<(), DALError> { - // Get idty_datas - let mut idty_datas = identities_db - .read(|db| db.get(pubkey).cloned())? - .expect("Fatal error : try to renewal unknow identity !"); - // Calculate new state value - idty_datas.state = if revert { - match idty_datas.state { - DALIdentityState::Member(renewed_counts) => { - let mut new_renewed_counts = renewed_counts.clone(); - new_renewed_counts[renewed_counts.len() - 1] -= 1; - if new_renewed_counts[renewed_counts.len() - 1] > 0 { - DALIdentityState::Member(new_renewed_counts) - } else { - DALIdentityState::ExpireMember(new_renewed_counts) - } - } - _ => panic!("Try to revert renewal_identity() for an excluded or revoked idty !"), - } - } else { - match idty_datas.state { - DALIdentityState::Member(renewed_counts) => { - let mut new_renewed_counts = renewed_counts.clone(); - new_renewed_counts[renewed_counts.len() - 1] += 1; - DALIdentityState::Member(new_renewed_counts) - } - DALIdentityState::ExpireMember(renewed_counts) => { - let mut new_renewed_counts = renewed_counts.clone(); - new_renewed_counts.push(0); - DALIdentityState::Member(new_renewed_counts) - } - _ => panic!("Try to renewed a revoked identity !"), - } - }; - // Calculate new ms_chainable_on value - if revert { - idty_datas.ms_chainable_on.pop(); - } else { - idty_datas - .ms_chainable_on - .push(renewal_timestamp + currency_params.ms_period); - } - // Write new identity datas - identities_db.write(|db| { - db.insert(*pubkey, idty_datas); - })?; - // Update MsExpirV10DB - ms_db.write(|db| { - let mut memberships = db.get(&ms_created_block_id).cloned().unwrap_or_default(); - memberships.insert(idty_wot_id); - db.insert(ms_created_block_id, memberships); - })?; - Ok(()) - } - - /// Remove identity from databases - pub fn remove_identity(db: &BinDB<IdentitiesV10Datas>, pubkey: PubKey) -> Result<(), DALError> { - db.write(|db| { - db.remove(&pubkey); - })?; - Ok(()) - } - - /// Get identity in databases - pub fn get_identity( - db: &BinDB<IdentitiesV10Datas>, - pubkey: &PubKey, - ) -> Result<Option<DALIdentity>, DALError> { - Ok(db.read(|db| { - if let Some(member_datas) = db.get(&pubkey) { - Some(member_datas.clone()) - } else { - None - } - })?) - } -} diff --git a/lib/modules/blockchain/blockchain-dal/constants.rs b/lib/modules/blockchain/blockchain-dal/src/constants.rs similarity index 100% rename from lib/modules/blockchain/blockchain-dal/constants.rs rename to lib/modules/blockchain/blockchain-dal/src/constants.rs diff --git a/lib/modules/blockchain/blockchain-dal/src/entities/block.rs b/lib/modules/blockchain/blockchain-dal/src/entities/block.rs new file mode 100644 index 0000000000000000000000000000000000000000..7d94c010ff2b3501172cd2e202f4f6416962b25c --- /dev/null +++ b/lib/modules/blockchain/blockchain-dal/src/entities/block.rs @@ -0,0 +1,43 @@ +// 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/>. + +use crate::*; +use dubp_documents::documents::block::BlockDocument; +use dubp_documents::Document; +use dubp_documents::{BlockId, Blockstamp}; +use durs_wot::NodeId; +use std::collections::HashMap; + +#[derive(Clone, Debug, Deserialize, Serialize)] +/// A block as it is saved in a database +pub struct DALBlock { + /// Fork id + pub fork_id: ForkId, + /// True only if the block is on an isolated fork + pub isolate: bool, + /// Block document + pub block: BlockDocument, + /// List of certifications that expire in this block. + /// Warning : BlockId contain the emission block, not the written block ! + /// HashMap<(Source, Target), CreatedBlockId> + pub expire_certs: Option<HashMap<(NodeId, NodeId), BlockId>>, +} + +impl DALBlock { + /// Get blockstamp + pub fn blockstamp(&self) -> Blockstamp { + self.block.blockstamp() + } +} diff --git a/lib/modules/blockchain/blockchain-dal/currency_params.rs b/lib/modules/blockchain/blockchain-dal/src/entities/currency_params.rs similarity index 89% rename from lib/modules/blockchain/blockchain-dal/currency_params.rs rename to lib/modules/blockchain/blockchain-dal/src/entities/currency_params.rs index 8e017048030a44348120ffe8b4ae3bc6a95f3697..28a65fc195d186796f6764bb86d446f54e0779dc 100644 --- a/lib/modules/blockchain/blockchain-dal/currency_params.rs +++ b/lib/modules/blockchain/blockchain-dal/src/entities/currency_params.rs @@ -138,23 +138,3 @@ impl CurrencyParameters { 1.0 / self.x_percent } } - -/// 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(&BlockId(0)) { - if genesis_block.block.parameters.is_some() { - Some(CurrencyParameters::from(( - genesis_block.block.currency.clone(), - genesis_block.block.parameters.expect("safe unwrap"), - ))) - } else { - panic!("The genesis block are None parameters !"); - } - } else { - None - } - })?) -} diff --git a/lib/modules/blockchain/blockchain-dal/src/entities/identity.rs b/lib/modules/blockchain/blockchain-dal/src/entities/identity.rs new file mode 100644 index 0000000000000000000000000000000000000000..6566527c7b2cbad49e3baba223bb4e0421122127 --- /dev/null +++ b/lib/modules/blockchain/blockchain-dal/src/entities/identity.rs @@ -0,0 +1,58 @@ +// 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/>. + +use dubp_documents::documents::identity::IdentityDocument; +use dubp_documents::{BlockId, Blockstamp}; +use durs_wot::NodeId; + +#[derive(Clone, Debug, Deserialize, Serialize)] +/// Identity state +pub enum DALIdentityState { + /// Member + Member(Vec<usize>), + /// Expire Member + ExpireMember(Vec<usize>), + /// Explicit Revoked + ExplicitRevoked(Vec<usize>), + /// Explicit Revoked after expire + ExplicitExpireRevoked(Vec<usize>), + /// Implicit revoked + ImplicitRevoked(Vec<usize>), +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +/// Identity in database +pub struct DALIdentity { + /// Identity hash + pub hash: String, + /// Identity state + pub state: DALIdentityState, + /// Blockstamp the identity was written + pub joined_on: Blockstamp, + /// Blockstamp the identity was expired + pub expired_on: Option<Blockstamp>, + /// Blockstamp the identity was revoked + pub revoked_on: Option<Blockstamp>, + /// Identity document + pub idty_doc: IdentityDocument, + /// Identity wot id + pub wot_id: NodeId, + /// Membership created block number + pub ms_created_block_id: BlockId, + /// Timestamp from which membership can be renewed + pub ms_chainable_on: Vec<u64>, + /// Timestamp from which the identity can write a new certification + pub cert_chainable_on: Vec<u64>, +} diff --git a/lib/modules/blockchain/blockchain-dal/src/entities/mod.rs b/lib/modules/blockchain/blockchain-dal/src/entities/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..d727fa2cb93c7222cab3eb8c45f669460a433c7f --- /dev/null +++ b/lib/modules/blockchain/blockchain-dal/src/entities/mod.rs @@ -0,0 +1,26 @@ +// Copyright (C) 2018 The Durs 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/>. + +/// Balances read functions +pub mod block; + +/// Certifications read functions +pub mod currency_params; + +/// Identities writer functions +pub mod identity; + +/// Databases write requests +pub mod sources; diff --git a/lib/modules/blockchain/blockchain-dal/sources.rs b/lib/modules/blockchain/blockchain-dal/src/entities/sources.rs similarity index 100% rename from lib/modules/blockchain/blockchain-dal/sources.rs rename to lib/modules/blockchain/blockchain-dal/src/entities/sources.rs diff --git a/lib/modules/blockchain/blockchain-dal/lib.rs b/lib/modules/blockchain/blockchain-dal/src/lib.rs similarity index 95% rename from lib/modules/blockchain/blockchain-dal/lib.rs rename to lib/modules/blockchain/blockchain-dal/src/lib.rs index 66cf116f0f9de50f1ce5329cf59c8366c3cce3bf..73c89c155af216ea5bf3e32f3b78764aa65be9a3 100644 --- a/lib/modules/blockchain/blockchain-dal/lib.rs +++ b/lib/modules/blockchain/blockchain-dal/src/lib.rs @@ -35,26 +35,14 @@ extern crate log; #[macro_use] extern crate serde_derive; -/// Define balance operations -pub mod balance; - -/// Blocks operations -pub mod block; - -/// Certifications operations -pub mod certs; - /// Define crate constants pub mod constants; -/// Currency parameters operations -pub mod currency_params; +/// Contains all entities stored in databases +pub mod entities; -/// Identity operations -pub mod identity; - -/// Define currency sources types -pub mod sources; +/// Contains all read databases functions +pub mod readers; /// Tools pub mod tools; @@ -81,9 +69,9 @@ use std::fs; use std::panic::UnwindSafe; use std::path::PathBuf; -use crate::block::DALBlock; -use crate::identity::DALIdentity; -use crate::sources::{SourceAmount, UTXOContentV10, UTXOIndexV10}; +use crate::entities::block::DALBlock; +use crate::entities::identity::DALIdentity; +use crate::entities::sources::{SourceAmount, UTXOContentV10, UTXOIndexV10}; use crate::writers::transaction::DALTxV10; #[derive(Debug, Deserialize, Copy, Clone, Ord, PartialEq, PartialOrd, Eq, Hash, Serialize)] @@ -94,6 +82,12 @@ pub struct ForkId(pub usize); pub type CurrencyParamsV10Datas = (CurrencyName, BlockV10Parameters); /// All blocks of local blockchain indexed by block number pub type LocalBlockchainV10Datas = HashMap<BlockId, DALBlock>; +/*/// Forks tree meta datas (block number and hash only) +pub type ForksTreeV10Datas = Tree<Blockstamp>; +/// Forks blocks referenced in tree indexed by their blockstamp +pub type ForksBlocksV10Datas = HashMap<Blockstamp, DALBlock>; +/// Forks blocks isolated indexed by their blockstamp +pub type ForksBlocksIsolatedV10Datas = HashMap<Blockstamp, DALBlock>;*/ /// Forks meta datas (block hash and previous hash only) pub type ForksV10Datas = HashMap<ForkId, HashMap<PreviousBlockstamp, BlockHash>>; /// Forks blocks indexed by their blockstamp diff --git a/lib/modules/blockchain/blockchain-dal/balance.rs b/lib/modules/blockchain/blockchain-dal/src/readers/balance.rs similarity index 97% rename from lib/modules/blockchain/blockchain-dal/balance.rs rename to lib/modules/blockchain/blockchain-dal/src/readers/balance.rs index 6cacb241d9b9369662fe6f2d733b267e36d0eded..3f142a88ac23b525fedbd0f4a3dd50fa47f532bb 100644 --- a/lib/modules/blockchain/blockchain-dal/balance.rs +++ b/lib/modules/blockchain/blockchain-dal/src/readers/balance.rs @@ -13,7 +13,7 @@ // 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::sources::*; +use crate::entities::sources::*; use crate::*; /// Get address balance diff --git a/lib/modules/blockchain/blockchain-dal/src/readers/block.rs b/lib/modules/blockchain/blockchain-dal/src/readers/block.rs new file mode 100644 index 0000000000000000000000000000000000000000..ce48f0f1543af672ed4e6a7bec740a23f6f9a40b --- /dev/null +++ b/lib/modules/blockchain/blockchain-dal/src/readers/block.rs @@ -0,0 +1,221 @@ +// Copyright (C) 2018 The Durs 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/>. + +use crate::constants::MAX_FORKS; +use crate::*; +use dubp_documents::documents::block::BlockDocument; +use dubp_documents::Document; +use dubp_documents::{BlockHash, BlockId, Blockstamp}; +use dup_crypto::keys::*; +use std::collections::HashMap; + +///Get forks status +pub fn get_forks( + forks_db: &BinDB<ForksV10Datas>, + current_blockstamp: Blockstamp, +) -> Result<Vec<ForkStatus>, DALError> { + Ok(forks_db.read(|forks_db| { + let blockchain_meta_datas = forks_db + .get(&ForkId(0)) + .expect("Fatal error : ForksV10DB not contain local chain !"); + let mut forks = Vec::new(); + for fork_id in 1..*MAX_FORKS { + if let Some(fork_meta_datas) = forks_db.get(&ForkId(fork_id)) { + if fork_meta_datas.is_empty() { + forks.push(ForkStatus::Free()); + } else if fork_meta_datas.contains_key(¤t_blockstamp) { + forks.push(ForkStatus::Stackable(ForkAlreadyCheck(false))); + } else { + let roll_back_max = if current_blockstamp.id.0 > 101 { + current_blockstamp.id.0 - 101 + } else { + 0 + }; + let mut max_common_block_id = None; + let mut too_old = false; + for previous_blockstamp in fork_meta_datas.keys() { + if blockchain_meta_datas.contains_key(&previous_blockstamp) { + if previous_blockstamp.id.0 >= roll_back_max { + if previous_blockstamp.id.0 + >= max_common_block_id.unwrap_or(BlockId(0)).0 + { + max_common_block_id = Some(previous_blockstamp.id); + too_old = false; + } + } else { + too_old = true; + } + } + } + if too_old { + forks.push(ForkStatus::TooOld(ForkAlreadyCheck(false))); + } else if let Some(max_common_block_id) = max_common_block_id { + forks.push(ForkStatus::RollBack( + ForkAlreadyCheck(false), + max_common_block_id, + )); + } else { + forks.push(ForkStatus::Isolate()); + } + } + } else { + forks.push(ForkStatus::Free()); + } + } + forks + })?) +} +/// get current blockstamp +pub fn get_current_blockstamp(blocks_db: &BlocksV10DBs) -> Result<Option<Blockstamp>, DALError> { + let current_previous_blockstamp = blocks_db.blockchain_db.read(|db| { + let blockchain_len = db.len() as u32; + if blockchain_len == 0 { + None + } else if let Some(dal_block) = db.get(&BlockId(blockchain_len - 1)) { + if blockchain_len > 1 { + Some(Blockstamp { + id: BlockId(blockchain_len - 2), + hash: BlockHash(dal_block.block.previous_hash), + }) + } else { + Some(Blockstamp::default()) + } + } else { + None + } + })?; + if current_previous_blockstamp.is_none() { + return Ok(None); + } + let current_previous_blockstamp = current_previous_blockstamp.expect("safe unwrap"); + if let Some(current_block_hash) = blocks_db.forks_db.read(|db| { + let blockchain_meta_datas = db + .get(&ForkId(0)) + .expect("Fatal error : ForksDB is incoherent, please reset data and resync !"); + blockchain_meta_datas + .get(¤t_previous_blockstamp) + .cloned() + })? { + Ok(Some(Blockstamp { + id: BlockId(current_previous_blockstamp.id.0 + 1), + hash: current_block_hash, + })) + } else { + Ok(None) + } +} + +/// Get block fork id +pub fn get_fork_id_of_blockstamp( + forks_blocks_db: &BinDB<ForksBlocksV10Datas>, + blockstamp: &Blockstamp, +) -> Result<Option<ForkId>, DALError> { + Ok(forks_blocks_db.read(|db| { + if let Some(dal_block) = db.get(blockstamp) { + Some(dal_block.fork_id) + } else { + None + } + })?) +} + +/// Get block hash +pub fn get_block_hash( + db: &BinDB<LocalBlockchainV10Datas>, + block_number: BlockId, +) -> Result<Option<BlockHash>, DALError> { + Ok(db.read(|db| { + if let Some(dal_block) = db.get(&block_number) { + dal_block.block.hash + } else { + None + } + })?) +} +/// Return true if the node already knows this block +pub fn already_have_block( + blockchain_db: &BinDB<LocalBlockchainV10Datas>, + forks_blocks_db: &BinDB<ForksBlocksV10Datas>, + blockstamp: Blockstamp, +) -> Result<bool, DALError> { + let already_have_block = forks_blocks_db.read(|db| db.contains_key(&blockstamp))?; + if !already_have_block { + Ok(blockchain_db.read(|db| { + if let Some(dal_block) = db.get(&blockstamp.id) { + if dal_block.block.hash.unwrap_or_default() == blockstamp.hash { + return true; + } + } + false + })?) + } else { + Ok(true) + } +} + +/// Get block +pub fn get_block( + blockchain_db: &BinDB<LocalBlockchainV10Datas>, + forks_blocks_db: Option<&BinDB<ForksBlocksV10Datas>>, + blockstamp: &Blockstamp, +) -> Result<Option<DALBlock>, DALError> { + let dal_block = blockchain_db.read(|db| db.get(&blockstamp.id).cloned())?; + if dal_block.is_none() && forks_blocks_db.is_some() { + Ok(forks_blocks_db + .expect("safe unwrap") + .read(|db| db.get(&blockstamp).cloned())?) + } else { + Ok(dal_block) + } +} +/// Get block in local blockchain +pub fn get_block_in_local_blockchain( + db: &BinDB<LocalBlockchainV10Datas>, + block_id: BlockId, +) -> Result<Option<BlockDocument>, DALError> { + Ok(db.read(|db| { + if let Some(dal_block) = db.get(&block_id) { + Some(dal_block.block.clone()) + } else { + None + } + })?) +} + +/// Get current frame of calculating members +pub fn get_current_frame( + current_block: &DALBlock, + db: &BinDB<LocalBlockchainV10Datas>, +) -> Result<HashMap<PubKey, usize>, DALError> { + let frame_begin = current_block.block.number.0 - current_block.block.issuers_frame as u32; + Ok(db.read(|db| { + let mut current_frame: HashMap<PubKey, usize> = HashMap::new(); + for block_number in frame_begin..current_block.block.number.0 { + let issuer = db + .get(&BlockId(block_number)) + .unwrap_or_else(|| panic!("Fail to get block #{} !", block_number)) + .block + .issuers()[0]; + let issuer_count_blocks = if let Some(issuer_count_blocks) = current_frame.get(&issuer) + { + issuer_count_blocks + 1 + } else { + 1 + }; + current_frame.insert(issuer, issuer_count_blocks); + } + current_frame + })?) +} diff --git a/lib/modules/blockchain/blockchain-dal/certs.rs b/lib/modules/blockchain/blockchain-dal/src/readers/certs.rs similarity index 100% rename from lib/modules/blockchain/blockchain-dal/certs.rs rename to lib/modules/blockchain/blockchain-dal/src/readers/certs.rs diff --git a/lib/modules/blockchain/blockchain-dal/src/readers/currency_params.rs b/lib/modules/blockchain/blockchain-dal/src/readers/currency_params.rs new file mode 100644 index 0000000000000000000000000000000000000000..d53287f47af9b6c784ffa1e694fba2b1863f368a --- /dev/null +++ b/lib/modules/blockchain/blockchain-dal/src/readers/currency_params.rs @@ -0,0 +1,37 @@ +// Copyright (C) 2018 The Durs 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/>. + +use crate::entities::currency_params::CurrencyParameters; +use crate::*; + +/// 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(&BlockId(0)) { + if genesis_block.block.parameters.is_some() { + Some(CurrencyParameters::from(( + genesis_block.block.currency.clone(), + genesis_block.block.parameters.expect("safe unwrap"), + ))) + } else { + panic!("The genesis block are None parameters !"); + } + } else { + None + } + })?) +} diff --git a/lib/modules/blockchain/blockchain-dal/src/readers/fork_tree.rs b/lib/modules/blockchain/blockchain-dal/src/readers/fork_tree.rs new file mode 100644 index 0000000000000000000000000000000000000000..c89daecd4570711390110e316a99089b423a0695 --- /dev/null +++ b/lib/modules/blockchain/blockchain-dal/src/readers/fork_tree.rs @@ -0,0 +1,81 @@ +// 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/>. + +use crate::constants::MAX_FORKS; +use crate::*; +use dubp_documents::{BlockId, Blockstamp, PreviousBlockstamp}; + +/// Get fork block +pub fn get_block_fork( + forks_db: &BinDB<ForksV10Datas>, + previous_blockstamp: &PreviousBlockstamp, +) -> Result<Option<ForkId>, DALError> { + Ok(forks_db.read(|forks_db| { + for (fork_id, fork_meta_datas) in forks_db { + if fork_meta_datas.contains_key(&previous_blockstamp) { + return Some(*fork_id); + } + } + None + })?) +} + +/// Get stackables blocks +pub fn get_stackables_blocks( + forks_db: &BinDB<ForksV10Datas>, + forks_blocks_db: &BinDB<ForksBlocksV10Datas>, + current_blockstamp: &Blockstamp, +) -> Result<Vec<DALBlock>, DALError> { + debug!("get_stackables_blocks() after {}", current_blockstamp); + let stackables_blocks_hashs = forks_db.read(|db| { + let mut stackables_blocks_hashs = Vec::new(); + for fork_meta_datas in db.values() { + if let Some(block_hash) = fork_meta_datas.get(¤t_blockstamp) { + stackables_blocks_hashs.push(*block_hash); + } + } + stackables_blocks_hashs + })?; + let stackables_blocks = forks_blocks_db.read(|db| { + let mut stackables_blocks = Vec::new(); + for stackable_block_hash in stackables_blocks_hashs { + if let Some(dal_block) = db.get(&Blockstamp { + id: BlockId(current_blockstamp.id.0 + 1), + hash: stackable_block_hash, + }) { + stackables_blocks.push(dal_block.clone()); + } + } + stackables_blocks + })?; + Ok(stackables_blocks) +} +/// Get stackables forks +pub fn get_stackables_forks( + db: &BinDB<ForksV10Datas>, + current_blockstamp: &Blockstamp, +) -> Result<Vec<usize>, DALError> { + Ok(db.read(|db| { + let mut stackables_forks = Vec::new(); + for f in 0..*MAX_FORKS { + if let Some(fork_meta_datas) = db.get(&ForkId(f)) { + if fork_meta_datas.get(¤t_blockstamp).is_some() { + stackables_forks.push(f); + } + } + } + stackables_forks + })?) +} diff --git a/lib/modules/blockchain/blockchain-dal/src/readers/identity.rs b/lib/modules/blockchain/blockchain-dal/src/readers/identity.rs new file mode 100644 index 0000000000000000000000000000000000000000..62fc573478fd73da215baba0289add72c4a07d4b --- /dev/null +++ b/lib/modules/blockchain/blockchain-dal/src/readers/identity.rs @@ -0,0 +1,77 @@ +// Copyright (C) 2018 The Durs 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/>. + +use crate::entities::identity::DALIdentity; +use crate::{BinDB, DALError, IdentitiesV10Datas}; +use dup_crypto::keys::*; +use durs_wot::NodeId; +use std::collections::HashMap; + +/// Get identity in databases +pub fn get_identity( + db: &BinDB<IdentitiesV10Datas>, + pubkey: &PubKey, +) -> Result<Option<DALIdentity>, DALError> { + Ok(db.read(|db| { + if let Some(member_datas) = db.get(&pubkey) { + Some(member_datas.clone()) + } else { + None + } + })?) +} + +/// Get uid from pubkey +pub fn get_uid( + identities_db: &BinDB<IdentitiesV10Datas>, + pubkey: PubKey, +) -> Result<Option<String>, DALError> { + Ok(identities_db.read(|db| { + if let Some(dal_idty) = db.get(&pubkey) { + Some(String::from(dal_idty.idty_doc.username())) + } else { + None + } + })?) +} + +/// Get pubkey from uid +pub fn get_pubkey_from_uid( + identities_db: &BinDB<IdentitiesV10Datas>, + uid: &str, +) -> Result<Option<PubKey>, DALError> { + Ok(identities_db.read(|db| { + for (pubkey, dal_idty) in db { + if uid == dal_idty.idty_doc.username() { + return Some(*pubkey); + } + } + None + })?) +} + +/// Get wot_id index +pub fn get_wot_index( + identities_db: &BinDB<IdentitiesV10Datas>, +) -> Result<HashMap<PubKey, NodeId>, DALError> { + Ok(identities_db.read(|db| { + let mut wot_index: HashMap<PubKey, NodeId> = HashMap::new(); + for (pubkey, member_datas) in db { + let wot_id = member_datas.wot_id; + wot_index.insert(*pubkey, wot_id); + } + wot_index + })?) +} diff --git a/lib/modules/blockchain/blockchain-dal/src/readers/mod.rs b/lib/modules/blockchain/blockchain-dal/src/readers/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..cbbabe500323a36d96fc6c4cbbb0859cc2778fc3 --- /dev/null +++ b/lib/modules/blockchain/blockchain-dal/src/readers/mod.rs @@ -0,0 +1,32 @@ +// Copyright (C) 2018 The Durs 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/>. + +/// Balances read functions +pub mod balance; + +/// Block read functions +pub mod block; + +/// Certifications read functions +pub mod certs; + +/// Currency params read functions +pub mod currency_params; + +/// Fork tree read functions +pub mod fork_tree; + +/// Identities read functions +pub mod identity; diff --git a/lib/modules/blockchain/blockchain-dal/tools.rs b/lib/modules/blockchain/blockchain-dal/src/tools.rs similarity index 78% rename from lib/modules/blockchain/blockchain-dal/tools.rs rename to lib/modules/blockchain/blockchain-dal/src/tools.rs index 34c55de52d15356be436dc70d3d340b94934876e..1a2e7dc8d2eda0989c7f4e03250d44606f2697e0 100644 --- a/lib/modules/blockchain/blockchain-dal/tools.rs +++ b/lib/modules/blockchain/blockchain-dal/src/tools.rs @@ -13,11 +13,14 @@ // 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::entities::block::DALBlock; +use dup_crypto::keys::PubKey; use durs_wot::operations::centrality::{CentralitiesCalculator, UlrikBrandesCentralityCalculator}; use durs_wot::operations::distance::{ DistanceCalculator, RustyDistanceCalculator, WotDistance, WotDistanceParameters, }; use durs_wot::{NodeId, WebOfTrust}; +use std::collections::HashMap; /// CENTRALITY_CALCULATOR pub static CENTRALITY_CALCULATOR: UlrikBrandesCentralityCalculator = @@ -136,3 +139,36 @@ pub fn compute_distances<T: WebOfTrust + Sync>( pub fn calculate_distance_stress_centralities<T: WebOfTrust>(wot: &T, step_max: u32) -> Vec<u64> { CENTRALITY_CALCULATOR.distance_stress_centralities(wot, step_max as usize) } + +/// Compute median issuers frame +pub fn compute_median_issuers_frame<S: std::hash::BuildHasher>( + current_block: DALBlock, + current_frame: &HashMap<PubKey, usize, S>, +) -> usize { + if !current_frame.is_empty() { + let mut current_frame_vec: Vec<_> = current_frame.values().cloned().collect(); + current_frame_vec.sort_unstable(); + + // Calculate median + let mut median_index = match current_block.block.issuers_count % 2 { + 1 => (current_block.block.issuers_count / 2) + 1, + _ => current_block.block.issuers_count / 2, + }; + if median_index >= current_block.block.issuers_count { + median_index = current_block.block.issuers_count - 1; + } + 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, + _ => (self.block.issuers_count as f64 * (2.0 / 3.0)) as usize, + }; + if second_tiercile_index >= self.block.issuers_count { + second_tiercile_index = self.block.issuers_count - 1; + } + self.second_tiercile_frame = current_frame_vec[second_tiercile_index];*/ + } else { + 0 + } +} diff --git a/lib/modules/blockchain/blockchain-dal/writers/block.rs b/lib/modules/blockchain/blockchain-dal/src/writers/block.rs similarity index 99% rename from lib/modules/blockchain/blockchain-dal/writers/block.rs rename to lib/modules/blockchain/blockchain-dal/src/writers/block.rs index d2d975ae8a647ed2a5a6b2cfa1afcffcb94a44d8..7024ce331c0d22366d06c69a9570d43a66c961e1 100644 --- a/lib/modules/blockchain/blockchain-dal/writers/block.rs +++ b/lib/modules/blockchain/blockchain-dal/src/writers/block.rs @@ -13,7 +13,7 @@ // 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::block::DALBlock; +use crate::entities::block::DALBlock; use crate::ForkId; use crate::{BinDB, DALError, ForksBlocksV10Datas, ForksV10Datas, LocalBlockchainV10Datas}; use dubp_documents::Document; diff --git a/lib/modules/blockchain/blockchain-dal/writers/certification.rs b/lib/modules/blockchain/blockchain-dal/src/writers/certification.rs similarity index 98% rename from lib/modules/blockchain/blockchain-dal/writers/certification.rs rename to lib/modules/blockchain/blockchain-dal/src/writers/certification.rs index 555ee97bc122071fda07e5dbec2f234e8412ce88..fb2b34c0513d5fbde621fa989344dbd04f58c67a 100644 --- a/lib/modules/blockchain/blockchain-dal/writers/certification.rs +++ b/lib/modules/blockchain/blockchain-dal/src/writers/certification.rs @@ -13,7 +13,7 @@ // 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::currency_params::CurrencyParameters; +use crate::entities::currency_params::CurrencyParameters; use crate::{BinDB, CertsExpirV10Datas, DALError, IdentitiesV10Datas}; use dubp_documents::documents::certification::CompactCertificationDocument; use dubp_documents::BlockId; diff --git a/lib/modules/blockchain/blockchain-dal/writers/dividend.rs b/lib/modules/blockchain/blockchain-dal/src/writers/dividend.rs similarity index 98% rename from lib/modules/blockchain/blockchain-dal/writers/dividend.rs rename to lib/modules/blockchain/blockchain-dal/src/writers/dividend.rs index be5e9c4efe29be08552891ff05817be1efef6807..710259f37cef1375995167e84ba7a3759c701b28 100644 --- a/lib/modules/blockchain/blockchain-dal/writers/dividend.rs +++ b/lib/modules/blockchain/blockchain-dal/src/writers/dividend.rs @@ -13,7 +13,7 @@ // 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::sources::SourceAmount; +use crate::entities::sources::SourceAmount; use crate::*; use dubp_documents::documents::transaction::*; use dubp_documents::BlockId; diff --git a/lib/modules/blockchain/blockchain-dal/src/writers/fork_tree.rs b/lib/modules/blockchain/blockchain-dal/src/writers/fork_tree.rs new file mode 100644 index 0000000000000000000000000000000000000000..e9350c5bbf3280e633734c943eb128ad0d5a61eb --- /dev/null +++ b/lib/modules/blockchain/blockchain-dal/src/writers/fork_tree.rs @@ -0,0 +1,91 @@ +// 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/>. + +use crate::constants::MAX_FORKS; +use crate::*; +use dubp_documents::*; + +/// Delete fork +pub fn delete_fork( + forks_db: &BinDB<ForksV10Datas>, + forks_blocks_db: &BinDB<ForksBlocksV10Datas>, + fork_id: ForkId, +) -> Result<(), DALError> { + let fork_meta_datas = forks_db + .read(|forks_db| forks_db.get(&fork_id).cloned())? + .expect("Fatal error : try to delete unknow fork"); + // Remove fork blocks + forks_blocks_db.write(|db| { + for (previous_blockstamp, hash) in fork_meta_datas { + let blockstamp = Blockstamp { + id: BlockId(previous_blockstamp.id.0 + 1), + hash, + }; + db.remove(&blockstamp); + } + })?; + // Remove fork meta datas + forks_db.write_safe(|db| { + db.remove(&fork_id); + })?; + Ok(()) +} +/// Assign fork id to new block +pub fn assign_fork_to_new_block( + forks_db: &BinDB<ForksV10Datas>, + new_block_previous_blockstamp: &PreviousBlockstamp, + new_block_hash: &BlockHash, +) -> Result<(Option<ForkId>, bool), DALError> { + let forks_meta_datas = forks_db.read(|forks_db| forks_db.clone())?; + // Try to assign block to an existing fork + for (fork_id, fork_meta_datas) in &forks_meta_datas { + let mut fork_datas = fork_meta_datas.clone(); + for (previous_blockstamp, hash) in fork_meta_datas { + let blockstamp = Blockstamp { + id: BlockId(previous_blockstamp.id.0 + 1), + hash: *hash, + }; + if *new_block_previous_blockstamp == blockstamp { + fork_datas.insert(*new_block_previous_blockstamp, *new_block_hash); + forks_db.write(|forks_db| { + forks_db.insert(*fork_id, fork_datas); + })?; + return Ok((Some(*fork_id), false)); + } + } + } + // Find an available fork + let mut new_fork_id = ForkId(0); + for f in 0..*MAX_FORKS { + if !forks_meta_datas.contains_key(&ForkId(f)) { + new_fork_id = ForkId(f); + break; + } + } + if new_fork_id.0 == 0 { + if forks_meta_datas.len() >= *MAX_FORKS { + return Ok((None, false)); + } else { + new_fork_id = ForkId(forks_meta_datas.len()); + } + } + // Create new fork + let mut new_fork = HashMap::new(); + new_fork.insert(*new_block_previous_blockstamp, *new_block_hash); + forks_db.write(|forks_db| { + forks_db.insert(new_fork_id, new_fork); + })?; + Ok((Some(new_fork_id), true)) +} diff --git a/lib/modules/blockchain/blockchain-dal/src/writers/identity.rs b/lib/modules/blockchain/blockchain-dal/src/writers/identity.rs new file mode 100644 index 0000000000000000000000000000000000000000..b0a24e8cc9b36b24d53f15b184160a202e4852bd --- /dev/null +++ b/lib/modules/blockchain/blockchain-dal/src/writers/identity.rs @@ -0,0 +1,248 @@ +// 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/>. + +use crate::entities::currency_params::CurrencyParameters; +use crate::entities::identity::{DALIdentity, DALIdentityState}; +use crate::{BinDB, DALError, IdentitiesV10Datas, MsExpirV10Datas}; +use dubp_documents::documents::identity::IdentityDocument; +use dubp_documents::Document; +use dubp_documents::{BlockId, Blockstamp}; +use dup_crypto::keys::PubKey; +use durs_wot::NodeId; + +/// Remove identity from databases +pub fn revert_create_identity( + identities_db: &BinDB<IdentitiesV10Datas>, + ms_db: &BinDB<MsExpirV10Datas>, + pubkey: &PubKey, +) -> Result<(), DALError> { + let dal_idty = identities_db.read(|db| { + db.get(&pubkey) + .expect("Fatal error : try to revert unknow identity !") + .clone() + })?; + // Remove membership + ms_db.write(|db| { + let mut memberships = db + .get(&dal_idty.ms_created_block_id) + .cloned() + .expect("Try to revert a membership that does not exist !"); + memberships.remove(&dal_idty.wot_id); + db.insert(dal_idty.ms_created_block_id, memberships); + })?; + // Remove identity + identities_db.write(|db| { + db.remove(&dal_idty.idty_doc.issuers()[0]); + })?; + Ok(()) +} + +/// Write identity in databases +pub fn create_identity( + currency_params: &CurrencyParameters, + identities_db: &BinDB<IdentitiesV10Datas>, + ms_db: &BinDB<MsExpirV10Datas>, + idty_doc: &IdentityDocument, + ms_created_block_id: BlockId, + wot_id: NodeId, + current_blockstamp: Blockstamp, + current_bc_time: u64, +) -> Result<(), DALError> { + let mut idty_doc = idty_doc.clone(); + idty_doc.reduce(); + let idty = DALIdentity { + hash: "0".to_string(), + state: DALIdentityState::Member(vec![0]), + joined_on: current_blockstamp, + expired_on: None, + revoked_on: None, + idty_doc, + wot_id, + ms_created_block_id, + ms_chainable_on: vec![current_bc_time + currency_params.ms_period], + cert_chainable_on: vec![], + }; + // Write Identity + identities_db.write(|db| { + db.insert(idty.idty_doc.issuers()[0], idty.clone()); + })?; + // Write membership + ms_db.write(|db| { + let mut memberships = db.get(&ms_created_block_id).cloned().unwrap_or_default(); + memberships.insert(wot_id); + db.insert(ms_created_block_id, memberships); + })?; + Ok(()) +} + +/// Apply "exclude identity" event +pub fn exclude_identity( + identities_db: &BinDB<IdentitiesV10Datas>, + pubkey: &PubKey, + exclusion_blockstamp: &Blockstamp, + revert: bool, +) -> Result<(), DALError> { + let mut idty_datas = identities_db + .read(|db| db.get(pubkey).cloned())? + .expect("Fatal error : try to renewal unknow identity !"); + idty_datas.state = if revert { + match idty_datas.state { + DALIdentityState::ExpireMember(renewed_counts) => { + DALIdentityState::Member(renewed_counts) + } + _ => panic!("Try to revert exclusion for a no excluded identity !"), + } + } else { + match idty_datas.state { + DALIdentityState::Member(renewed_counts) => { + DALIdentityState::ExpireMember(renewed_counts) + } + _ => panic!("Try to exclude for an already excluded/revoked identity !"), + } + }; + idty_datas.expired_on = if revert { + None + } else { + Some(*exclusion_blockstamp) + }; + // Write new identity datas + identities_db.write(|db| { + db.insert(*pubkey, idty_datas); + })?; + Ok(()) +} + +/// Apply "revoke identity" event +pub fn revoke_identity( + identities_db: &BinDB<IdentitiesV10Datas>, + pubkey: &PubKey, + renewal_blockstamp: &Blockstamp, + explicit: bool, + revert: bool, +) -> Result<(), DALError> { + let mut member_datas = identities_db + .read(|db| db.get(pubkey).cloned())? + .expect("Fatal error : Try to revoke unknow idty !"); + + member_datas.state = if revert { + match member_datas.state { + DALIdentityState::ExplicitRevoked(renewed_counts) => { + DALIdentityState::Member(renewed_counts) + } + DALIdentityState::ExplicitExpireRevoked(renewed_counts) + | DALIdentityState::ImplicitRevoked(renewed_counts) => { + DALIdentityState::ExpireMember(renewed_counts) + } + _ => panic!("Try to revert revoke_identity() for a no revoked idty !"), + } + } else { + match member_datas.state { + DALIdentityState::ExpireMember(renewed_counts) => { + DALIdentityState::ExplicitExpireRevoked(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 !"), + } + }; + member_datas.revoked_on = if revert { + None + } else { + Some(*renewal_blockstamp) + }; + + identities_db.write(|db| { + db.insert(*pubkey, member_datas); + })?; + Ok(()) +} + +/// Apply "renewal identity" event in databases +pub fn renewal_identity( + currency_params: &CurrencyParameters, + identities_db: &BinDB<IdentitiesV10Datas>, + ms_db: &BinDB<MsExpirV10Datas>, + pubkey: &PubKey, + idty_wot_id: NodeId, + renewal_timestamp: u64, + ms_created_block_id: BlockId, + revert: bool, +) -> Result<(), DALError> { + // Get idty_datas + let mut idty_datas = identities_db + .read(|db| db.get(pubkey).cloned())? + .expect("Fatal error : try to renewal unknow identity !"); + // Calculate new state value + idty_datas.state = if revert { + match idty_datas.state { + DALIdentityState::Member(renewed_counts) => { + let mut new_renewed_counts = renewed_counts.clone(); + new_renewed_counts[renewed_counts.len() - 1] -= 1; + if new_renewed_counts[renewed_counts.len() - 1] > 0 { + DALIdentityState::Member(new_renewed_counts) + } else { + DALIdentityState::ExpireMember(new_renewed_counts) + } + } + _ => panic!("Try to revert renewal_identity() for an excluded or revoked idty !"), + } + } else { + match idty_datas.state { + DALIdentityState::Member(renewed_counts) => { + let mut new_renewed_counts = renewed_counts.clone(); + new_renewed_counts[renewed_counts.len() - 1] += 1; + DALIdentityState::Member(new_renewed_counts) + } + DALIdentityState::ExpireMember(renewed_counts) => { + let mut new_renewed_counts = renewed_counts.clone(); + new_renewed_counts.push(0); + DALIdentityState::Member(new_renewed_counts) + } + _ => panic!("Try to renewed a revoked identity !"), + } + }; + // Calculate new ms_chainable_on value + if revert { + idty_datas.ms_chainable_on.pop(); + } else { + idty_datas + .ms_chainable_on + .push(renewal_timestamp + currency_params.ms_period); + } + // Write new identity datas + identities_db.write(|db| { + db.insert(*pubkey, idty_datas); + })?; + // Update MsExpirV10DB + ms_db.write(|db| { + let mut memberships = db.get(&ms_created_block_id).cloned().unwrap_or_default(); + memberships.insert(idty_wot_id); + db.insert(ms_created_block_id, memberships); + })?; + Ok(()) +} + +/// Remove identity from databases +pub fn remove_identity(db: &BinDB<IdentitiesV10Datas>, pubkey: PubKey) -> Result<(), DALError> { + db.write(|db| { + db.remove(&pubkey); + })?; + Ok(()) +} diff --git a/lib/modules/blockchain/blockchain-dal/writers/mod.rs b/lib/modules/blockchain/blockchain-dal/src/writers/mod.rs similarity index 95% rename from lib/modules/blockchain/blockchain-dal/writers/mod.rs rename to lib/modules/blockchain/blockchain-dal/src/writers/mod.rs index e27c72a0623a9331478ed68e40db9df821f249c3..7960d1daa9a398f09c77092087d120c5ed3c1007 100644 --- a/lib/modules/blockchain/blockchain-dal/writers/mod.rs +++ b/lib/modules/blockchain/blockchain-dal/src/writers/mod.rs @@ -22,6 +22,9 @@ pub mod certification; /// Dividend apply functions pub mod dividend; +/// Fork tree writer functions +pub mod fork_tree; + /// Identities writer functions pub mod identity; diff --git a/lib/modules/blockchain/blockchain-dal/writers/requests.rs b/lib/modules/blockchain/blockchain-dal/src/writers/requests.rs similarity index 92% rename from lib/modules/blockchain/blockchain-dal/writers/requests.rs rename to lib/modules/blockchain/blockchain-dal/src/writers/requests.rs index 09be3a2f24eab7992f3640504bf7fdf7e2db3b5f..e057340816ce16fec7b4d3509d59efcb1fa8876b 100644 --- a/lib/modules/blockchain/blockchain-dal/writers/requests.rs +++ b/lib/modules/blockchain/blockchain-dal/src/writers/requests.rs @@ -13,10 +13,9 @@ // 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::block::DALBlock; -use crate::currency_params::CurrencyParameters; -use crate::identity::DALIdentity; -use crate::sources::SourceAmount; +use crate::entities::block::DALBlock; +use crate::entities::currency_params::CurrencyParameters; +use crate::entities::sources::SourceAmount; use crate::writers::transaction::DALTxV10; use crate::*; use dubp_documents::documents::certification::CompactCertificationDocument; @@ -152,9 +151,7 @@ impl WotsDBsWriteQuery { ms_created_block_id, ) => { trace!("WotsDBsWriteQuery::RenewalIdentity..."); - let mut idty = DALIdentity::get_identity(&databases.identities_db, pubkey)? - .expect("Fatal error : impossible to renewal an identidy that don't exist !"); - idty.renewal_identity( + writers::identity::renewal_identity( currency_params, &databases.identities_db, &databases.ms_db, @@ -172,9 +169,7 @@ impl WotsDBsWriteQuery { ref current_bc_time, ms_created_block_id, ) => { - let mut idty = DALIdentity::get_identity(&databases.identities_db, pubkey)? - .expect("Fatal error : impossible to renewal an identidy that don't exist !"); - idty.renewal_identity( + writers::identity::renewal_identity( currency_params, &databases.identities_db, &databases.ms_db, @@ -186,13 +181,23 @@ impl WotsDBsWriteQuery { )?; } WotsDBsWriteQuery::ExcludeIdentity(ref pubkey, ref blockstamp) => { - DALIdentity::exclude_identity(&databases.identities_db, pubkey, blockstamp, false)?; + writers::identity::exclude_identity( + &databases.identities_db, + pubkey, + blockstamp, + false, + )?; } WotsDBsWriteQuery::RevertExcludeIdentity(ref pubkey, ref blockstamp) => { - DALIdentity::exclude_identity(&databases.identities_db, pubkey, blockstamp, true)?; + writers::identity::exclude_identity( + &databases.identities_db, + pubkey, + blockstamp, + true, + )?; } WotsDBsWriteQuery::RevokeIdentity(ref pubkey, ref blockstamp, ref explicit) => { - DALIdentity::revoke_identity( + writers::identity::revoke_identity( &databases.identities_db, pubkey, blockstamp, @@ -201,7 +206,7 @@ impl WotsDBsWriteQuery { )?; } WotsDBsWriteQuery::RevertRevokeIdentity(ref pubkey, ref blockstamp, ref explicit) => { - DALIdentity::revoke_identity( + writers::identity::revoke_identity( &databases.identities_db, pubkey, blockstamp, diff --git a/lib/modules/blockchain/blockchain-dal/writers/transaction.rs b/lib/modules/blockchain/blockchain-dal/src/writers/transaction.rs similarity index 99% rename from lib/modules/blockchain/blockchain-dal/writers/transaction.rs rename to lib/modules/blockchain/blockchain-dal/src/writers/transaction.rs index bb7994ab09398f01029f1e59dc99029df1c089a3..dfe76768b23c4459f3ae364e8551ab007ed6f27f 100644 --- a/lib/modules/blockchain/blockchain-dal/writers/transaction.rs +++ b/lib/modules/blockchain/blockchain-dal/src/writers/transaction.rs @@ -15,7 +15,7 @@ use dubp_documents::documents::transaction::*; -use crate::sources::{SourceAmount, SourceIndexV10, UTXOIndexV10, UTXOV10}; +use crate::entities::sources::{SourceAmount, SourceIndexV10, UTXOIndexV10, UTXOV10}; use crate::*; #[derive(Debug, Copy, Clone)] diff --git a/lib/modules/blockchain/blockchain-dal/writers/identity.rs b/lib/modules/blockchain/blockchain-dal/writers/identity.rs deleted file mode 100644 index 09d04757c2298536b7c1a1d520a4653106bb594a..0000000000000000000000000000000000000000 --- a/lib/modules/blockchain/blockchain-dal/writers/identity.rs +++ /dev/null @@ -1,88 +0,0 @@ -// 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/>. - -use crate::currency_params::CurrencyParameters; -use crate::identity::{DALIdentity, DALIdentityState}; -use crate::{BinDB, DALError, IdentitiesV10Datas, MsExpirV10Datas}; -use dubp_documents::documents::identity::IdentityDocument; -use dubp_documents::Document; -use dubp_documents::{BlockId, Blockstamp}; -use dup_crypto::keys::PubKey; -use durs_wot::NodeId; - -/// Remove identity from databases -pub fn revert_create_identity( - identities_db: &BinDB<IdentitiesV10Datas>, - ms_db: &BinDB<MsExpirV10Datas>, - pubkey: &PubKey, -) -> Result<(), DALError> { - let dal_idty = identities_db.read(|db| { - db.get(&pubkey) - .expect("Fatal error : try to revert unknow identity !") - .clone() - })?; - // Remove membership - ms_db.write(|db| { - let mut memberships = db - .get(&dal_idty.ms_created_block_id) - .cloned() - .expect("Try to revert a membership that does not exist !"); - memberships.remove(&dal_idty.wot_id); - db.insert(dal_idty.ms_created_block_id, memberships); - })?; - // Remove identity - identities_db.write(|db| { - db.remove(&dal_idty.idty_doc.issuers()[0]); - })?; - Ok(()) -} - -/// Write identity in databases -pub fn create_identity( - currency_params: &CurrencyParameters, - identities_db: &BinDB<IdentitiesV10Datas>, - ms_db: &BinDB<MsExpirV10Datas>, - idty_doc: &IdentityDocument, - ms_created_block_id: BlockId, - wot_id: NodeId, - current_blockstamp: Blockstamp, - current_bc_time: u64, -) -> Result<(), DALError> { - let mut idty_doc = idty_doc.clone(); - idty_doc.reduce(); - let idty = DALIdentity { - hash: "0".to_string(), - state: DALIdentityState::Member(vec![0]), - joined_on: current_blockstamp, - expired_on: None, - revoked_on: None, - idty_doc, - wot_id, - ms_created_block_id, - ms_chainable_on: vec![current_bc_time + currency_params.ms_period], - cert_chainable_on: vec![], - }; - // Write Identity - identities_db.write(|db| { - db.insert(idty.idty_doc.issuers()[0], idty.clone()); - })?; - // Write membership - ms_db.write(|db| { - let mut memberships = db.get(&ms_created_block_id).cloned().unwrap_or_default(); - memberships.insert(wot_id); - db.insert(ms_created_block_id, memberships); - })?; - Ok(()) -} diff --git a/lib/modules/blockchain/blockchain/apply_valid_block.rs b/lib/modules/blockchain/blockchain/apply_valid_block.rs index a4e4683b88c417fdf9db9701103dcf1c0e6c2db3..c5f11c999d1ba54999143002b1be220fabb854c4 100644 --- a/lib/modules/blockchain/blockchain/apply_valid_block.rs +++ b/lib/modules/blockchain/blockchain/apply_valid_block.rs @@ -18,8 +18,8 @@ use dubp_documents::documents::transaction::{TxAmount, TxBase}; use dubp_documents::BlockId; use dubp_documents::Document; use dup_crypto::keys::*; -use durs_blockchain_dal::block::DALBlock; -use durs_blockchain_dal::sources::SourceAmount; +use durs_blockchain_dal::entities::block::DALBlock; +use durs_blockchain_dal::entities::sources::SourceAmount; use durs_blockchain_dal::writers::requests::*; use durs_blockchain_dal::{BinDB, ForkId}; use durs_wot::data::{NewLinkResult, RemLinkResult}; diff --git a/lib/modules/blockchain/blockchain/check_and_apply_block.rs b/lib/modules/blockchain/blockchain/check_and_apply_block.rs index 93226ab22644194a1400579238b4abf3bb4fb46d..8ca69a7b6a687c00e21bdae6d3663b07074950c5 100644 --- a/lib/modules/blockchain/blockchain/check_and_apply_block.rs +++ b/lib/modules/blockchain/blockchain/check_and_apply_block.rs @@ -21,7 +21,7 @@ use crate::*; use dubp_documents::Document; use dubp_documents::{BlockHash, BlockId, Blockstamp, PreviousBlockstamp}; use dup_crypto::keys::*; -use durs_blockchain_dal::block::DALBlock; +use durs_blockchain_dal::entities::block::DALBlock; use durs_blockchain_dal::*; #[derive(Debug, Copy, Clone)] @@ -66,7 +66,7 @@ pub fn check_and_apply_block<W: WebOfTrust>( // Get BlockDocument && check if already have block let already_have_block = if block_from_network { - DALBlock::already_have_block( + readers::block::already_have_block( &blocks_databases.blockchain_db, &blocks_databases.forks_blocks_db, block_doc.blockstamp(), @@ -90,11 +90,11 @@ pub fn check_and_apply_block<W: WebOfTrust>( // Detect expire_certs let blocks_expiring = Vec::with_capacity(0); let expire_certs = - durs_blockchain_dal::certs::find_expire_certs(certs_db, blocks_expiring)?; + durs_blockchain_dal::readers::certs::find_expire_certs(certs_db, blocks_expiring)?; // Try stack up block let old_fork_id = if block_from_network { - durs_blockchain_dal::block::get_fork_id_of_blockstamp( + durs_blockchain_dal::readers::block::get_fork_id_of_blockstamp( &blocks_databases.forks_blocks_db, &block_doc.blockstamp(), )? @@ -126,7 +126,7 @@ pub fn check_and_apply_block<W: WebOfTrust>( "stackable_block : block {} not chainable, store this for future !", block_doc.blockstamp() ); - let (fork_id, new_fork) = DALBlock::assign_fork_to_new_block( + let (fork_id, new_fork) = writers::fork_tree::assign_fork_to_new_block( &blocks_databases.forks_db, &PreviousBlockstamp { id: BlockId(block_doc.number.0 - 1), diff --git a/lib/modules/blockchain/blockchain/dbex.rs b/lib/modules/blockchain/blockchain/dbex.rs index 97fdb82aa03af89d023a36a382ce3d195744693a..dd690b2b4199116945242f2f50fa8a900c9de5b1 100644 --- a/lib/modules/blockchain/blockchain/dbex.rs +++ b/lib/modules/blockchain/blockchain/dbex.rs @@ -17,7 +17,6 @@ use crate::*; use dubp_documents::documents::transaction::*; use duniter_module::DuniterConf; use dup_crypto::keys::*; -use durs_blockchain_dal::identity::DALIdentity; use durs_wot::data::rusty::RustyWebOfTrust; use durs_wot::operations::distance::{DistanceCalculator, WotDistance, WotDistanceParameters}; use std::time::*; @@ -80,11 +79,12 @@ pub fn dbex_tx<DC: DuniterConf>(profile: &str, conf: &DC, _csv: bool, query: &DB DBExTxQuery::Balance(ref address_str) => { let pubkey = if let Ok(ed25519_pubkey) = ed25519::PublicKey::from_base58(address_str) { PubKey::Ed25519(ed25519_pubkey) - } else if let Some(pubkey) = durs_blockchain_dal::identity::get_pubkey_from_uid( - &wot_databases.identities_db, - address_str, - ) - .expect("get_uid : DALError") + } else if let Some(pubkey) = + durs_blockchain_dal::readers::identity::get_pubkey_from_uid( + &wot_databases.identities_db, + address_str, + ) + .expect("get_uid : DALError") { pubkey } else { @@ -92,7 +92,7 @@ pub fn dbex_tx<DC: DuniterConf>(profile: &str, conf: &DC, _csv: bool, query: &DB return; }; let address = UTXOConditionsGroup::Single(TransactionOutputCondition::Sig(pubkey)); - let address_balance = durs_blockchain_dal::balance::get_address_balance( + let address_balance = durs_blockchain_dal::readers::balance::get_address_balance( ¤cy_databases.balances_db, &address, ) @@ -140,7 +140,8 @@ pub fn dbex_wot<DC: DuniterConf>(profile: &str, conf: &DC, csv: bool, query: &DB .expect("Fail to parse currency params !"); // get wot_index - let wot_index = DALIdentity::get_wot_index(&wot_databases.identities_db).expect("DALError"); + let wot_index = + readers::identity::get_wot_index(&wot_databases.identities_db).expect("DALError"); // get wot_reverse_index let wot_reverse_index: HashMap<NodeId, &PubKey> = @@ -270,7 +271,7 @@ pub fn dbex_wot<DC: DuniterConf>(profile: &str, conf: &DC, csv: bool, query: &DB } DBExWotQuery::MemberDatas(ref uid) => { println!(" Members count = {}.", members_count); - if let Some(pubkey) = durs_blockchain_dal::identity::get_pubkey_from_uid( + if let Some(pubkey) = durs_blockchain_dal::readers::identity::get_pubkey_from_uid( &wot_databases.identities_db, uid, ) @@ -309,7 +310,7 @@ pub fn dbex_wot<DC: DuniterConf>(profile: &str, conf: &DC, csv: bool, query: &DB .expect("Fail to get links source !"); println!("Certifiers : {}", sources.len()); for (i, source) in sources.iter().enumerate() { - let source_uid = durs_blockchain_dal::identity::get_uid( + let source_uid = durs_blockchain_dal::readers::identity::get_uid( &wot_databases.identities_db, *(wot_reverse_index[&source]), ) diff --git a/lib/modules/blockchain/blockchain/lib.rs b/lib/modules/blockchain/blockchain/lib.rs index 65bdad2c910346d8360609552459e366e8be08d4..d4357cf2ccebd7fd8c476b6199006cc77cf0bd6e 100644 --- a/lib/modules/blockchain/blockchain/lib.rs +++ b/lib/modules/blockchain/blockchain/lib.rs @@ -64,9 +64,7 @@ use duniter_network::{ requests::{NetworkResponse, OldNetworkRequest}, }; use dup_crypto::keys::*; -use durs_blockchain_dal::block::DALBlock; -use durs_blockchain_dal::currency_params::CurrencyParameters; -use durs_blockchain_dal::identity::DALIdentity; +use durs_blockchain_dal::entities::currency_params::CurrencyParameters; use durs_blockchain_dal::writers::requests::BlocksDBsWriteQuery; use durs_blockchain_dal::*; use durs_common_tools::fatal_error; @@ -194,11 +192,11 @@ impl BlockchainModule { // Get current blockstamp let current_blockstamp = - durs_blockchain_dal::block::get_current_blockstamp(&blocks_databases) + durs_blockchain_dal::readers::block::get_current_blockstamp(&blocks_databases) .expect("Fatal error : fail to read Blockchain DB !"); // Get currency parameters - let currency_params = durs_blockchain_dal::currency_params::get_currency_params( + let currency_params = durs_blockchain_dal::readers::currency_params::get_currency_params( &blocks_databases.blockchain_db, ) .expect("Fatal error : fail to read Blockchain DB !") @@ -206,8 +204,11 @@ impl BlockchainModule { // Get forks states let forks_states = if let Some(current_blockstamp) = current_blockstamp { - durs_blockchain_dal::block::get_forks(&blocks_databases.forks_db, current_blockstamp) - .expect("Fatal error : fail to read Forks DB !") + durs_blockchain_dal::readers::block::get_forks( + &blocks_databases.forks_db, + current_blockstamp, + ) + .expect("Fatal error : fail to read Forks DB !") } else { vec![] }; @@ -407,7 +408,7 @@ impl BlockchainModule { } current_blockstamp = block_doc.blockstamp(); // Update forks states - self.forks_states = durs_blockchain_dal::block::get_forks( + self.forks_states = durs_blockchain_dal::readers::block::get_forks( &self.blocks_databases.forks_db, current_blockstamp, ) @@ -472,7 +473,7 @@ impl BlockchainModule { { current_blockstamp = blockstamp; // Update forks states - self.forks_states = durs_blockchain_dal::block::get_forks( + self.forks_states = durs_blockchain_dal::readers::block::get_forks( &self.blocks_databases.forks_db, current_blockstamp, ) @@ -521,7 +522,7 @@ impl BlockchainModule { // Get wot index let mut wot_index: HashMap<PubKey, NodeId> = - DALIdentity::get_wot_index(&self.wot_databases.identities_db) + readers::identity::get_wot_index(&self.wot_databases.identities_db) .expect("Fatal eror : get_wot_index : Fail to read blockchain databases"); // Open wot file @@ -529,7 +530,7 @@ impl BlockchainModule { // Get current block let mut current_blockstamp = - durs_blockchain_dal::block::get_current_blockstamp(&self.blocks_databases) + durs_blockchain_dal::readers::block::get_current_blockstamp(&self.blocks_databases) .expect("Fatal error : fail to read ForksV10DB !") .unwrap_or_default(); @@ -598,7 +599,7 @@ impl BlockchainModule { ); if let Some(current_block) = - DALBlock::get_block( + readers::block::get_block( &self.blocks_databases.blockchain_db, None, ¤t_blockstamp, @@ -624,7 +625,7 @@ impl BlockchainModule { .iter() .map(|p| ( *p, - durs_blockchain_dal::identity::get_uid(&self.wot_databases.identities_db, *p) + durs_blockchain_dal::readers::identity::get_uid(&self.wot_databases.identities_db, *p) .expect("Fatal error : get_uid : Fail to read WotV10DB !") )) .collect(), @@ -734,7 +735,7 @@ impl BlockchainModule { current_blockstamp = new_current_blockstamp; // Update forks states self.forks_states = - durs_blockchain_dal::block::get_forks( + durs_blockchain_dal::readers::block::get_forks( &self.blocks_databases.forks_db, current_blockstamp, ) @@ -768,7 +769,7 @@ impl BlockchainModule { last_get_stackables_blocks = now; loop { let stackable_blocks = - durs_blockchain_dal::block::DALBlock::get_stackables_blocks( + durs_blockchain_dal::readers::fork_tree::get_stackables_blocks( &self.blocks_databases.forks_db, &self.blocks_databases.forks_blocks_db, ¤t_blockstamp, @@ -829,7 +830,7 @@ impl BlockchainModule { } else { warn!("fail to stackable_block({})", stackable_block_number); // Delete this fork - DALBlock::delete_fork( + writers::fork_tree::delete_fork( &self.blocks_databases.forks_db, &self.blocks_databases.forks_blocks_db, stackable_block.fork_id, diff --git a/lib/modules/blockchain/blockchain/revert_block.rs b/lib/modules/blockchain/blockchain/revert_block.rs index 4721eda00ffa058025664240073a820d37e0d313..bbb7bcf9ec0a13aeb9c09fb5dc8ef0bdcaf386fe 100644 --- a/lib/modules/blockchain/blockchain/revert_block.rs +++ b/lib/modules/blockchain/blockchain/revert_block.rs @@ -17,8 +17,8 @@ use dubp_documents::documents::block::TxDocOrTxHash; use dubp_documents::documents::transaction::{TxAmount, TxBase}; use dubp_documents::Document; use dup_crypto::keys::*; -use durs_blockchain_dal::block::DALBlock; -use durs_blockchain_dal::sources::SourceAmount; +use durs_blockchain_dal::entities::block::DALBlock; +use durs_blockchain_dal::entities::sources::SourceAmount; use durs_blockchain_dal::writers::requests::*; use durs_blockchain_dal::writers::transaction::DALTxV10; use durs_blockchain_dal::{BinDB, ForkId, TxV10Datas}; diff --git a/lib/modules/blockchain/blockchain/sync/download/json_reader_worker.rs b/lib/modules/blockchain/blockchain/sync/download/json_reader_worker.rs index 4d44db5694412e91f6c2ac83fdb34ebb27b068db..ac7f5878abe348a172815928792540304c0154f3 100644 --- a/lib/modules/blockchain/blockchain/sync/download/json_reader_worker.rs +++ b/lib/modules/blockchain/blockchain/sync/download/json_reader_worker.rs @@ -98,7 +98,7 @@ pub fn json_reader_worker( let db_path = duniter_conf::get_blockchain_db_path(&profile, &last_block.currency); let blocks_databases = BlocksV10DBs::open(Some(&db_path)); let current_blockstamp: Blockstamp = - durs_blockchain_dal::block::get_current_blockstamp(&blocks_databases) + durs_blockchain_dal::readers::block::get_current_blockstamp(&blocks_databases) .expect("ForksV10DB : RustBreakError !") .unwrap_or_default(); info!("Local current blockstamp = {}", current_blockstamp); diff --git a/lib/modules/blockchain/blockchain/sync/mod.rs b/lib/modules/blockchain/blockchain/sync/mod.rs index 46641d81624d5d110c44e41f171534a936f18099..13277da5a53f1bd5a724f71b0fc4eee2051b7ab0 100644 --- a/lib/modules/blockchain/blockchain/sync/mod.rs +++ b/lib/modules/blockchain/blockchain/sync/mod.rs @@ -19,7 +19,7 @@ mod download; use crate::*; use dubp_documents::{BlockHash, BlockId}; use dup_crypto::keys::*; -use durs_blockchain_dal::currency_params::CurrencyParameters; +use durs_blockchain_dal::entities::currency_params::CurrencyParameters; use durs_blockchain_dal::writers::requests::*; use durs_blockchain_dal::ForkId; use durs_common_tools::fatal_error; @@ -142,7 +142,7 @@ pub fn local_sync<DC: DuniterConf>( // Get local current blockstamp debug!("Get local current blockstamp..."); let mut current_blockstamp: Blockstamp = - durs_blockchain_dal::block::get_current_blockstamp(&databases) + durs_blockchain_dal::readers::block::get_current_blockstamp(&databases) .expect("DALError : fail to get current blockstamp !") .unwrap_or_default(); debug!("Success to get local current blockstamp."); @@ -155,7 +155,7 @@ pub fn local_sync<DC: DuniterConf>( // Get wot index let mut wot_index: HashMap<PubKey, NodeId> = - DALIdentity::get_wot_index(&wot_databases.identities_db) + readers::identity::get_wot_index(&wot_databases.identities_db) .expect("Fatal eror : get_wot_index : Fail to read blockchain databases"); // Start sync @@ -276,7 +276,7 @@ pub fn local_sync<DC: DuniterConf>( } // Find expire_certs let expire_certs = - durs_blockchain_dal::certs::find_expire_certs(&certs_db, blocks_expiring) + durs_blockchain_dal::readers::certs::find_expire_certs(&certs_db, blocks_expiring) .expect("find_expire_certs() : DALError"); // Get block blockstamp let blockstamp = block_doc.blockstamp(); diff --git a/lib/modules/blockchain/blockchain/verify_block.rs b/lib/modules/blockchain/blockchain/verify_block.rs index 2d67b00ffd0ba8dd2790e313e610225f3cf6c0fe..c4d4df0d198fd265786e03b6543875932f67fbc0 100644 --- a/lib/modules/blockchain/blockchain/verify_block.rs +++ b/lib/modules/blockchain/blockchain/verify_block.rs @@ -17,7 +17,6 @@ use crate::check_and_apply_block::BlockError; use dubp_documents::documents::block::BlockDocument; use dubp_documents::*; use dup_crypto::keys::PubKey; -use durs_blockchain_dal::block::DALBlock; use durs_blockchain_dal::*; use durs_wot::*; use std::collections::HashMap; @@ -38,8 +37,10 @@ pub fn verify_block_validity<W: WebOfTrust>( // Rules that do not concern genesis block if block.number.0 > 0 { // Get previous block - let previous_block_opt = - DALBlock::get_block_in_local_blockchain(blockchain_db, BlockId(block.number.0 - 1))?; + let previous_block_opt = readers::block::get_block_in_local_blockchain( + blockchain_db, + BlockId(block.number.0 - 1), + )?; // Previous block must exist if previous_block_opt.is_none() {