diff --git a/Cargo.lock b/Cargo.lock index 4cdc79e78552cd483bd6096c7a437f0c507881fb..d7dd4bcdb78ba89763b3e6d2eb67a6b15238d29c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -84,15 +84,6 @@ dependencies = [ "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bincode" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "bincode" version = "1.0.0" @@ -409,7 +400,7 @@ dependencies = [ name = "duniter-wotb" version = "0.8.0-a0.6" dependencies = [ - "bincode 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1443,7 +1434,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557" "checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" "checksum base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9263aa6a38da271eec5c91a83ce1e800f093c8535788d403d626d8d5c3f8f007" -"checksum bincode 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a6301db0b49fb63551bc15b5ae348147101cdf323242b93ec7546d5002ff1af" "checksum bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" diff --git a/blockchain/apply_valid_block.rs b/blockchain/apply_valid_block.rs index 204148a3e13447fcc50232e7a3d738f3c25e03e5..26b31cbcde6fb39f54f73a7a701dbc3926443d23 100644 --- a/blockchain/apply_valid_block.rs +++ b/blockchain/apply_valid_block.rs @@ -17,14 +17,16 @@ use duniter_crypto::keys::*; use duniter_dal::block::DALBlock; use duniter_dal::sources::SourceAmount; use duniter_dal::writers::requests::*; -use duniter_dal::ForkId; +use duniter_dal::{BinDB, ForkId}; use duniter_documents::blockchain::v10::documents::transaction::{TxAmount, TxBase}; use duniter_documents::blockchain::v10::documents::BlockDocument; use duniter_documents::blockchain::Document; use duniter_documents::BlockId; use duniter_wotb::data::NewLinkResult; use duniter_wotb::{NodeId, WebOfTrust}; +use rustbreak::backend::Backend; use std::collections::HashMap; +use std::fmt::Debug; #[derive(Debug)] /// Stores all queries to apply in database to "apply" the block @@ -41,10 +43,10 @@ pub enum ApplyValidBlockError { RevokeUnknowNodeId(), } -pub fn apply_valid_block<W: WebOfTrust + Sync>( +pub fn apply_valid_block<W: WebOfTrust, B: Backend + Debug>( block: &BlockDocument, wot_index: &mut HashMap<PubKey, NodeId>, - wot: &mut W, + wot_db: &BinDB<W, B>, expire_certs: &HashMap<(NodeId, NodeId), BlockId>, old_fork_id: Option<ForkId>, ) -> Result<ValidBlockApplyReqs, ApplyValidBlockError> { @@ -63,8 +65,16 @@ pub fn apply_valid_block<W: WebOfTrust + Sync>( let pubkey = joiner.clone().issuers()[0]; if let Some(idty_doc) = identities.get(&pubkey) { // Newcomer - let wotb_id = NodeId(wot.size()); - wot.add_node(); + let wotb_id = NodeId( + wot_db + .read(|db| db.size()) + .expect("Fatal error : fail to read WotDB !"), + ); + wot_db + .write(|db| { + db.add_node(); + }) + .expect("Fail to write in WotDB"); wot_index.insert(pubkey, wotb_id); wot_dbs_requests.push(WotsDBsWriteQuery::CreateIdentity( wotb_id, @@ -76,7 +86,11 @@ pub fn apply_valid_block<W: WebOfTrust + Sync>( } else { // Renewer let wotb_id = wot_index[&joiner.issuers()[0]]; - wot.set_enabled(wotb_id, true); + wot_db + .write(|db| { + db.set_enabled(wotb_id, true); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::RenewalIdentity( joiner.issuers()[0], wotb_id, @@ -89,7 +103,11 @@ pub fn apply_valid_block<W: WebOfTrust + Sync>( let pubkey = active.issuers()[0]; if !identities.contains_key(&pubkey) { let wotb_id = wot_index[&pubkey]; - wot.set_enabled(wotb_id, true); + wot_db + .write(|db| { + db.set_enabled(wotb_id, true); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::RenewalIdentity( pubkey, wotb_id, @@ -104,7 +122,11 @@ pub fn apply_valid_block<W: WebOfTrust + Sync>( } else { return Err(ApplyValidBlockError::ExcludeUnknowNodeId()); }; - wot.set_enabled(*wot_id, false); + wot_db + .write(|db| { + db.set_enabled(*wot_id, false); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::ExcludeIdentity( exclusion, block.blockstamp(), @@ -117,7 +139,11 @@ pub fn apply_valid_block<W: WebOfTrust + Sync>( } else { return Err(ApplyValidBlockError::RevokeUnknowNodeId()); }; - wot.set_enabled(*wot_id, false); + wot_db + .write(|db| { + db.set_enabled(*wot_id, false); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::RevokeIdentity( compact_revoc.issuer, block.blockstamp(), @@ -128,14 +154,18 @@ pub fn apply_valid_block<W: WebOfTrust + Sync>( let compact_cert = certification.to_compact_document(); let wotb_node_from = wot_index[&compact_cert.issuer]; let wotb_node_to = wot_index[&compact_cert.target]; - let result = wot.add_link(wotb_node_from, wotb_node_to); - match result { - NewLinkResult::Ok(_) => {} - _ => panic!( - "Fail to add_link {}->{} : {:?}", - wotb_node_from.0, wotb_node_to.0, result - ), - } + wot_db + .write(|db| { + let result = db.add_link(wotb_node_from, wotb_node_to); + match result { + NewLinkResult::Ok(_) => {} + _ => panic!( + "Fail to add_link {}->{} : {:?}", + wotb_node_from.0, wotb_node_to.0, result + ), + } + }) + .expect("Fail to read WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::CreateCert( compact_cert.issuer, wotb_node_from, @@ -154,7 +184,9 @@ pub fn apply_valid_block<W: WebOfTrust + Sync>( } if let Some(du_amount) = block.dividend { if du_amount > 0 { - let members_wot_ids = wot.get_enabled(); + let members_wot_ids = wot_db + .read(|db| db.get_enabled()) + .expect("Fail to read WotDB"); let mut members_pubkeys = Vec::new(); for (pubkey, wotb_id) in wot_index { if members_wot_ids.contains(wotb_id) { diff --git a/blockchain/check_and_apply_block.rs b/blockchain/check_and_apply_block.rs index 0a426a8ebba69861397c5445dcf7f40a2beec8e6..21f4e567fa561a9850164e43b389645e1d5a8580 100644 --- a/blockchain/check_and_apply_block.rs +++ b/blockchain/check_and_apply_block.rs @@ -22,6 +22,8 @@ use duniter_dal::*; use duniter_documents::blockchain::Document; use duniter_documents::{BlockHash, BlockId, Blockstamp, PreviousBlockstamp}; use duniter_network::NetworkBlock; +use rustbreak::backend::Backend; +use std::fmt::Debug; use *; #[derive(Debug, Copy, Clone)] @@ -53,13 +55,13 @@ impl From<ApplyValidBlockError> for BlockError { } } -pub fn check_and_apply_block<W: WebOfTrust + Sync>( +pub fn check_and_apply_block<W: WebOfTrust, B: Backend + Debug>( blocks_databases: &BlocksV10DBs, certs_db: &BinFileDB<CertsExpirV10Datas>, block: &Block, current_blockstamp: &Blockstamp, wotb_index: &mut HashMap<PubKey, NodeId>, - wot: &mut W, + wot_db: &BinDB<W, B>, forks_states: &[ForkStatus], ) -> Result<ValidBlockApplyReqs, BlockError> { let (block_doc, already_have_block) = match *block { @@ -102,7 +104,7 @@ pub fn check_and_apply_block<W: WebOfTrust + Sync>( return Ok(apply_valid_block( &block_doc, wotb_index, - wot, + wot_db, &expire_certs, old_fork_id, )?); diff --git a/blockchain/dbex.rs b/blockchain/dbex.rs index a1efe2b42252ea2364e5030fb23b999917cb81c7..9999f311c2c37e3c1ff977632b21dfc898f140c2 100644 --- a/blockchain/dbex.rs +++ b/blockchain/dbex.rs @@ -16,7 +16,6 @@ use duniter_crypto::keys::*; use duniter_dal::identity::DALIdentity; use duniter_documents::blockchain::v10::documents::transaction::*; -use duniter_documents::Blockstamp; use duniter_module::DuniterConf; use duniter_wotb::data::rusty::RustyWebOfTrust; use std::time::*; @@ -135,18 +134,17 @@ pub fn dbex_wot(conf: &DuniterConf, query: &DBExWotQuery) { let wot_reverse_index: HashMap<NodeId, &PubKey> = wot_index.iter().map(|(p, id)| (*id, p)).collect(); - // Get wot path - let wot_path = duniter_conf::get_wot_path(conf.profile().clone().to_string(), &conf.currency()); - - // Open wot file - let (wot, wot_blockstamp): (RustyWebOfTrust, Blockstamp) = - open_wot_file(&WOT_FILE_FORMATER, &wot_path, *INFINITE_SIG_STOCK); + // Open wot db + let wot_db = open_wot_db::<RustyWebOfTrust>(&db_path).expect("Fail to open WotDB !"); // Print wot blockstamp - println!("Wot : Current blockstamp = {}.", wot_blockstamp); + //println!("Wot : Current blockstamp = {}.", wot_blockstamp); // Print members count - let members_count = wot.get_enabled().len(); + let members_count = wot_db + .read(|db| db.get_enabled()) + .expect("Fail to read WotDB") + .len(); println!(" Members count = {}.", members_count); match *query { @@ -162,8 +160,9 @@ pub fn dbex_wot(conf: &DuniterConf, query: &DBExWotQuery) { wot_id.0, pubkey.to_string() ); - let sources = wot - .get_links_source(wot_id) + let sources = wot_db + .read(|db| db.get_links_source(wot_id)) + .expect("Fail to read WotDB") .expect("Fail to get links source !"); println!("Certifiers : {}", sources.len()); for (i, source) in sources.iter().enumerate() { diff --git a/blockchain/lib.rs b/blockchain/lib.rs index a676c924789855f9951210589febc859696e5ef4..c7ef4ec4c8d4d2712d77faeea781c64d5e6ba0d1 100644 --- a/blockchain/lib.rs +++ b/blockchain/lib.rs @@ -47,6 +47,7 @@ mod ts_parsers; use std::collections::HashMap; use std::env; +use std::fmt::Debug; use std::ops::Deref; use std::path::PathBuf; use std::str; @@ -73,9 +74,8 @@ use duniter_network::{ NetworkBlock, NetworkDocument, NetworkEvent, NetworkRequest, NetworkResponse, NodeFullId, }; use duniter_wotb::data::rusty::RustyWebOfTrust; -use duniter_wotb::operations::file::BinaryFileFormater; use duniter_wotb::{NodeId, WebOfTrust}; -use rustbreak::backend::FileBackend; +use rustbreak::backend::{Backend, FileBackend}; /// The blocks are requested by packet groups. This constant sets the block packet size. pub static CHUNK_SIZE: &'static u32 = &50; @@ -83,8 +83,6 @@ pub static CHUNK_SIZE: &'static u32 = &50; pub static INFINITE_SIG_STOCK: &'static usize = &4_000_000_000; /// The blocks are requested by packet groups. This constant sets the number of packets per group. pub static MAX_BLOCKS_REQUEST: &'static u32 = &500; -/// There can be several implementations of the wot file backup, this constant fixes the implementation used by the blockchain module. -pub static WOT_FILE_FORMATER: BinaryFileFormater = BinaryFileFormater {}; /// Blockchain Module #[derive(Debug)] @@ -300,12 +298,12 @@ impl BlockchainModule { } } } - fn receive_network_documents<W: WebOfTrust + Sync>( + fn receive_network_documents<W: WebOfTrust, B: Backend + Debug>( &mut self, network_documents: &[NetworkDocument], current_blockstamp: &Blockstamp, wotb_index: &mut HashMap<PubKey, NodeId>, - wot: &mut W, + wot_db: &BinDB<W, B>, ) -> Blockstamp { let mut blockchain_documents = Vec::new(); let mut current_blockstamp = *current_blockstamp; @@ -321,7 +319,7 @@ impl BlockchainModule { &Block::NetworkBlock(network_block), ¤t_blockstamp, wotb_index, - wot, + wot_db, &self.forks_states, ) { Ok(ValidBlockApplyReqs(block_req, wot_dbs_reqs, currency_dbs_reqs)) => { @@ -440,12 +438,12 @@ impl BlockchainModule { } } } - fn receive_blocks<W: WebOfTrust + Sync>( + fn receive_blocks<W: WebOfTrust, B: Backend + Debug>( &mut self, blocks_in_box: &[Box<NetworkBlock>], current_blockstamp: &Blockstamp, wotb_index: &mut HashMap<PubKey, NodeId>, - wot: &mut W, + wot: &BinDB<W, B>, ) -> Blockstamp { debug!("BlockchainModule : receive_blocks()"); let blocks: Vec<&NetworkBlock> = blocks_in_box.into_iter().map(|b| b.deref()).collect(); @@ -455,7 +453,7 @@ impl BlockchainModule { let mut save_currency_dbs = false; for block in blocks { if let Ok(ValidBlockApplyReqs(bc_db_query, wot_dbs_queries, tx_dbs_queries)) = - check_and_apply_block::<W>( + check_and_apply_block::<W, B>( &self.blocks_databases, &self.wot_databases.certs_db, &Block::NetworkBlock(block), @@ -513,8 +511,9 @@ impl BlockchainModule { pub fn start_blockchain(&mut self, blockchain_receiver: &mpsc::Receiver<DuniterMessage>) -> () { info!("BlockchainModule::start_blockchain()"); - // Get wot path - let wot_path = duniter_conf::get_wot_path(self.conf_profile.clone(), &self.currency); + // Get dbs path + let dbs_path = + duniter_conf::get_blockchain_db_path(self.conf_profile.as_str(), &self.currency); // Get wotb index let mut wotb_index: HashMap<PubKey, NodeId> = @@ -522,11 +521,7 @@ impl BlockchainModule { .expect("Fatal eror : get_wotb_index : Fail to read blockchain databases"); // Open wot file - let (mut wot, mut _wot_blockstamp) = open_wot_file::<RustyWebOfTrust, BinaryFileFormater>( - &WOT_FILE_FORMATER, - &wot_path, - self.currency_params.sig_stock, - ); + let wot_db = open_wot_db::<RustyWebOfTrust>(&dbs_path).expect("Fail to open WotDB !"); // Get current block let mut current_blockstamp = duniter_dal::block::get_current_blockstamp( @@ -640,7 +635,7 @@ impl BlockchainModule { network_docs, ¤t_blockstamp, &mut wotb_index, - &mut wot, + &wot_db, ); current_blockstamp = new_current_blockstamp; } @@ -667,7 +662,7 @@ impl BlockchainModule { blocks, ¤t_blockstamp, &mut wotb_index, - &mut wot, + &wot_db, ); if current_blockstamp != new_current_blockstamp { current_blockstamp = new_current_blockstamp; @@ -728,7 +723,7 @@ impl BlockchainModule { &Block::LocalBlock(&stackable_block.block), ¤t_blockstamp, &mut wotb_index, - &mut wot, + &wot_db, &self.forks_states, ) { // Apply db requests diff --git a/blockchain/sync.rs b/blockchain/sync.rs index 5d5c29df4e1f9b0980177354b9b454686d14b90e..2f5c2f0f8a18371fb6396bb3575bb425a4f3c6f6 100644 --- a/blockchain/sync.rs +++ b/blockchain/sync.rs @@ -26,8 +26,7 @@ use duniter_dal::writers::requests::*; use duniter_dal::ForkId; use duniter_documents::{BlockHash, BlockId, Hash}; use duniter_network::NetworkBlock; -use duniter_wotb::operations::file::FileFormater; -use duniter_wotb::{NodeId, WebOfTrust}; +use duniter_wotb::NodeId; use rustbreak::{deser::Bincode, MemoryDatabase}; use std::collections::{HashMap, VecDeque}; use std::fs; @@ -80,34 +79,10 @@ pub fn sync_ts( let mut current_blockstamp = *current_blockstamp; // Get wot path - let wot_path = duniter_conf::get_wot_path(profile.clone().to_string(), currency); - - // Open wot file - let (mut wot, mut _wot_blockstamp): (RustyWebOfTrust, Blockstamp) = - if wot_path.as_path().exists() { - match WOT_FILE_FORMATER.from_file( - wot_path - .as_path() - .to_str() - .expect("Fail to convert path to str"), - *INFINITE_SIG_STOCK, - ) { - Ok((wot, binary_blockstamp)) => match str::from_utf8(&binary_blockstamp) { - Ok(str_blockstamp) => ( - wot, - Blockstamp::from_string(str_blockstamp) - .expect("Fail to deserialize wot blockcstamp"), - ), - Err(e) => panic!("Invalid UTF-8 sequence: {}", e), - }, - Err(e) => panic!("Fatal Error : fail te read wot file : {:?}", e), - } - } else { - ( - RustyWebOfTrust::new(*INFINITE_SIG_STOCK), - Blockstamp::default(), - ) - }; + let db_path = duniter_conf::get_blockchain_db_path(&profile, ¤cy); + + // Open wot db + let wot_db = open_wot_db::<RustyWebOfTrust>(&db_path).expect("Fail to open WotDB !"); // Get verification level let _verif_level = if cautious { @@ -496,7 +471,6 @@ pub fn sync_ts( block_doc.currency.clone(), block_doc.parameters.unwrap(), )); - wot.set_max_link(currency_params.sig_stock); get_currency_params = true; } else { panic!("The genesis block are None parameters !"); @@ -522,10 +496,10 @@ pub fn sync_ts( // Apply block let apply_valid_block_begin = SystemTime::now(); if let Ok(ValidBlockApplyReqs(block_req, wot_db_reqs, currency_db_reqs)) = - apply_valid_block::<RustyWebOfTrust>( + apply_valid_block::<RustyWebOfTrust, FileBackend>( &block_doc, &mut wotb_index, - &mut wot, + &wot_db, &expire_certs, None, ) { @@ -609,13 +583,7 @@ pub fn sync_ts( info!("Sync : send End signal to tx job."); // Save wot file - WOT_FILE_FORMATER - .to_file( - &wot, - current_blockstamp.to_string().as_bytes(), - wot_path.as_path().to_str().unwrap(), - ) - .expect("Fatal Error: Fail to write wotb in file !"); + wot_db.save().expect("Fail to save wotb db"); let main_job_duration = SystemTime::now().duration_since(main_job_begin).unwrap() - all_wait_duration; diff --git a/dal/lib.rs b/dal/lib.rs index 3327c62df8bdb567fe46dc85336fcc5c346c7801..3704a8db7c901b3f0b6005af0028c109bb637003 100644 --- a/dal/lib.rs +++ b/dal/lib.rs @@ -52,7 +52,6 @@ pub mod writers; use duniter_crypto::keys::*; use duniter_documents::blockchain::v10::documents::transaction::*; use duniter_documents::{BlockHash, BlockId, Blockstamp, Hash, PreviousBlockstamp}; -use duniter_wotb::operations::file::FileFormater; use duniter_wotb::{NodeId, WebOfTrust}; use rustbreak::backend::{Backend, FileBackend, MemoryBackend}; use rustbreak::error::{RustbreakError, RustbreakErrorKind}; @@ -326,12 +325,13 @@ pub fn open_db<D: Serialize + DeserializeOwned + Debug + Default + Clone + Send> } } -/// Open wot file (cf. duniter-wot crate) -pub fn open_wot_file<W: WebOfTrust, WF: FileFormater>( - file_formater: &WF, - wot_path: &PathBuf, - sig_stock: usize, -) -> (W, Blockstamp) { +/// Open wot db (cf. duniter-wot crate) +pub fn open_wot_db<W: WebOfTrust>(dbs_folder_path: &PathBuf) -> Result<BinFileDB<W>, DALError> { + open_db::<W>(dbs_folder_path, "wot.db") +} + +// Open wot file (cf. duniter-wot crate) +/*pub fn open_wot_file<W: WebOfTrust>(wot_path: &PathBuf, sig_stock: usize) -> (W, Blockstamp) { if wot_path.as_path().exists() { match file_formater.from_file( wot_path @@ -353,4 +353,4 @@ pub fn open_wot_file<W: WebOfTrust, WF: FileFormater>( } else { (W::new(sig_stock), Blockstamp::default()) } -} +}*/ diff --git a/wotb/Cargo.toml b/wotb/Cargo.toml index f6fb7144516a36cbd0c2da7a0d6ab6ccd13c99ef..cabd64653d52a0cdb2d67b4640e0bb228bdeeee7 100644 --- a/wotb/Cargo.toml +++ b/wotb/Cargo.toml @@ -14,7 +14,7 @@ path = "lib.rs" [dependencies] serde = "1.0.57" serde_derive = "1.0.57" -bincode = "0.9.2" +bincode = "1.0.0" byteorder = "1.2.3" rayon = "1.0.1" diff --git a/wotb/data/legacy.rs b/wotb/data/legacy.rs deleted file mode 100644 index 6a38cf5d6d0b0edeb95c90366351f4d4bb4f3204..0000000000000000000000000000000000000000 --- a/wotb/data/legacy.rs +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright (C) 2017-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/>. - -//! Provide a legacy implementation of `WebOfTrust` storage and calculations. -//! Its mostly translated directly from the original C++ code. - -use std::collections::hash_set::Iter; -use std::collections::HashSet; -use std::fs::File; -use std::io::prelude::*; - -use bincode::{deserialize, serialize, Infinite}; - -use super::{HasLinkResult, NewLinkResult, RemLinkResult}; -use NodeId; -use WebOfTrust; - -#[derive(Debug, Clone, Serialize, Deserialize)] -struct Node { - id: NodeId, - /// Is the node enabled ? - pub enabled: bool, - certs: HashSet<NodeId>, - issued_count: usize, -} - -impl Node { - /// Create a new node. - pub fn new(id: usize) -> Node { - Node { - id: NodeId(id), - enabled: true, - certs: HashSet::new(), - issued_count: 0, - } - } - - /// Getter of node id. - pub fn id(&self) -> NodeId { - self.id - } - - /// Add a certification from this node to the given node. - /// - /// Certification will fail if this node already used all its certs. - pub fn link_to(&mut self, to: &mut Node, max_certs: usize) -> NewLinkResult { - if self.issued_count >= max_certs { - NewLinkResult::AllCertificationsUsed(to.certs.len()) - } else if to.certs.contains(&self.id()) { - NewLinkResult::AlreadyCertified(to.certs.len()) - } else { - to.certs.insert(self.id()); - self.issued_count += 1; - NewLinkResult::Ok(to.certs.len()) - } - } - - /// Remove a certification (if it exist) from this node to the given node. - pub fn unlink_to(&mut self, to: &mut Node) -> RemLinkResult { - if to.certs.contains(&self.id()) { - to.certs.remove(&self.id()); - self.issued_count -= 1; - RemLinkResult::Removed(to.certs.len()) - } else { - RemLinkResult::UnknownCert(to.certs.len()) - } - } - - /// Tells if this node has a link from the given node. - pub fn has_link_from(&self, from: &Node) -> bool { - self.certs.contains(&from.id()) - } - - /// Tells if this node has a link to the given node. - pub fn has_link_to(&self, to: &Node) -> bool { - to.has_link_from(self) - } - - /// Give an iterator of node certs. - pub fn links_iter(&self) -> Iter<NodeId> { - self.certs.iter() - } - - /// Getter of the issued count. - pub fn issued_count(&self) -> usize { - self.issued_count - } -} - -/// Store a Web of Trust. -/// -/// Allow to create/remove nodes and links between them. -/// -/// It provides methods to find sentries nodes, find all paths -/// between 2 nodes and to compute distances in the web. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct LegacyWebOfTrust { - nodes: Vec<Node>, - /// Maxiumum amout of certifications a node can provide. - /// - /// It can be changed afterward, and will be accounted for every future calculations. - /// - /// In practice it should not change after initialization. - pub max_cert: usize, -} - -impl LegacyWebOfTrust { - /// Read `WoT` from file. - pub fn legacy_from_file(path: &str) -> Option<LegacyWebOfTrust> { - let mut file = match File::open(path) { - Ok(file) => file, - Err(_) => return None, - }; - - let mut content: Vec<u8> = vec![]; - if file.read_to_end(&mut content).is_err() { - return None; - } - - match deserialize::<LegacyWebOfTrust>(&content[..]) { - Ok(wot) => Some(wot), - Err(_) => None, - } - } - - /// Write `WoT` to file. - pub fn legacy_to_file(&self, path: &str) -> bool { - let encoded: Vec<u8> = serialize(self, Infinite).unwrap(); - - match File::create(path) { - Ok(mut buffer) => buffer.write_all(&encoded).is_ok(), - Err(_) => false, - } - } -} - -impl WebOfTrust for LegacyWebOfTrust { - fn new(max_cert: usize) -> LegacyWebOfTrust { - LegacyWebOfTrust { - nodes: vec![], - max_cert, - } - } - - fn get_max_link(&self) -> usize { - self.max_cert - } - - fn set_max_link(&mut self, max_link: usize) { - self.max_cert = max_link; - } - - fn add_node(&mut self) -> NodeId { - let node_id = self.nodes.len(); - self.nodes.push(Node::new(node_id)); - - NodeId(node_id) - } - - fn rem_node(&mut self) -> Option<NodeId> { - self.nodes.pop(); - - if !self.nodes.is_empty() { - Some(NodeId(self.nodes.iter().len() - 1)) - } else { - None - } - } - - fn size(&self) -> usize { - self.nodes.iter().count() - } - - fn is_enabled(&self, node: NodeId) -> Option<bool> { - if node.0 >= self.size() { - None - } else { - Some(self.nodes[node.0].enabled) - } - } - - fn set_enabled(&mut self, node: NodeId, state: bool) -> Option<bool> { - if node.0 >= self.size() { - None - } else { - self.nodes[node.0].enabled = state; - Some(state) - } - } - - fn get_enabled(&self) -> Vec<NodeId> { - self.nodes - .iter() - .filter(|x| x.enabled) - .map(|x| x.id()) - .collect() - } - - fn get_disabled(&self) -> Vec<NodeId> { - self.nodes - .iter() - .filter(|x| !x.enabled) - .map(|x| x.id()) - .collect() - } - - fn add_link(&mut self, from: NodeId, to: NodeId) -> NewLinkResult { - if from.0 == to.0 { - NewLinkResult::SelfLinkingForbidden() - } else if from.0 >= self.size() { - NewLinkResult::UnknownSource() - } else if to.0 >= self.size() { - NewLinkResult::UnknownTarget() - } else if from.0 < to.0 { - // split `nodes` in two part to allow borrowing 2 nodes at the same time - let (start, end) = self.nodes.split_at_mut(to.0); - start[from.0].link_to(&mut end[0], self.max_cert) - } else { - // split `nodes` in two part to allow borrowing 2 nodes at the same time - let (start, end) = self.nodes.split_at_mut(from.0); - end[0].link_to(&mut start[to.0], self.max_cert) - } - } - - fn rem_link(&mut self, from: NodeId, to: NodeId) -> RemLinkResult { - if from.0 >= self.size() { - RemLinkResult::UnknownSource() - } else if to.0 >= self.size() { - RemLinkResult::UnknownTarget() - } else if from.0 < to.0 { - // split `nodes` in two part to allow borrowing 2 nodes at the same time - let (start, end) = self.nodes.split_at_mut(to.0); - start[from.0].unlink_to(&mut end[0]) - } else { - // split `nodes` in two part to allow borrowing 2 nodes at the same time - let (start, end) = self.nodes.split_at_mut(from.0); - end[0].unlink_to(&mut start[to.0]) - } - } - - fn has_link(&self, from: NodeId, to: NodeId) -> HasLinkResult { - if from.0 >= self.size() { - HasLinkResult::UnknownSource() - } else if to.0 >= self.size() { - HasLinkResult::UnknownTarget() - } else { - HasLinkResult::Link(self.nodes[from.0].has_link_to(&self.nodes[to.0])) - } - } - - fn is_sentry(&self, node: NodeId, sentry_requirement: usize) -> Option<bool> { - if node.0 >= self.size() { - return None; - } - - let node = &self.nodes[node.0]; - - Some( - node.enabled - && node.issued_count() >= sentry_requirement - && node.links_iter().count() >= sentry_requirement, - ) - } - - fn get_sentries(&self, sentry_requirement: usize) -> Vec<NodeId> { - self.nodes - .iter() - .filter(|x| { - x.enabled - && x.issued_count() >= sentry_requirement - && x.links_iter().count() >= sentry_requirement - }) - .map(|x| x.id()) - .collect() - } - - fn get_non_sentries(&self, sentry_requirement: usize) -> Vec<NodeId> { - self.nodes - .iter() - .filter(|x| { - x.enabled - && (x.issued_count < sentry_requirement - || x.links_iter().count() < sentry_requirement) - }) - .map(|x| x.id()) - .collect() - } - - fn get_links_source(&self, target: NodeId) -> Option<Vec<NodeId>> { - if target.0 >= self.size() { - None - } else { - Some(self.nodes[target.0].certs.iter().cloned().collect()) - } - } - - fn issued_count(&self, id: NodeId) -> Option<usize> { - if id.0 >= self.size() { - None - } else { - Some(self.nodes[id.0].issued_count) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use tests::generic_wot_test; - - #[test] - fn node_tests() { - // Correct node id - assert_eq!(Node::new(1).id().0, 1); - - // Create 2 nodes - let mut node1 = Node::new(1); - let mut node2 = Node::new(2); - - // Default value - assert_eq!(node1.issued_count(), 0); - assert_eq!(node2.links_iter().count(), 0); - assert!(!node1.has_link_to(&node2)); - assert!(!node2.has_link_to(&node2)); - assert!(!node1.has_link_from(&node1)); - assert!(!node2.has_link_from(&node1)); - - // New link 1 -> 2 - match node1.link_to(&mut node2, 10) { - NewLinkResult::Ok(1) => (), - _ => panic!(), - }; - - assert_eq!(node1.issued_count(), 1); - assert_eq!(node2.links_iter().count(), 1); - assert!(node1.has_link_to(&node2)); - assert!(!node2.has_link_to(&node2)); - assert!(!node1.has_link_from(&node1)); - assert!(node2.has_link_from(&node1)); - - // Existing link 1 -> 2 - match node1.link_to(&mut node2, 10) { - NewLinkResult::AlreadyCertified(1) => (), - _ => panic!(), - }; - - assert_eq!(node1.issued_count(), 1); - assert_eq!(node2.links_iter().count(), 1); - assert!(node1.has_link_to(&node2)); - assert!(!node2.has_link_to(&node2)); - assert!(!node1.has_link_from(&node1)); - assert!(node2.has_link_from(&node1)); - - // Max certification count - let mut node3 = Node::new(3); - match node1.link_to(&mut node3, 1) { - NewLinkResult::AllCertificationsUsed(0) => (), - _ => panic!(), - }; - - assert_eq!(node1.issued_count(), 1); - assert_eq!(node2.links_iter().count(), 1); - assert_eq!(node3.links_iter().count(), 0); - assert!(node1.has_link_to(&node2)); - assert!(!node2.has_link_to(&node2)); - assert!(!node1.has_link_from(&node1)); - assert!(node2.has_link_from(&node1)); - } - - #[test] - fn wot_tests() { - generic_wot_test::<LegacyWebOfTrust>(); - } -} diff --git a/wotb/data/mod.rs b/wotb/data/mod.rs index 4d7752398358d3b09b788775323ee2bac68dbe4d..fe6beec488891f4a6943b0b87a2fc92b58db9b88 100644 --- a/wotb/data/mod.rs +++ b/wotb/data/mod.rs @@ -17,9 +17,12 @@ //! `LegacyWebOfTrust` is almost a translation of the legacy C++ coden while //! `RustyWebOfTrust` is a brand new implementation with a more "rusty" style. -pub mod legacy; pub mod rusty; +use serde::de::DeserializeOwned; +use serde::Serialize; +use std::fmt::Debug; + /// Wrapper for a node id. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct NodeId(pub usize); @@ -70,7 +73,7 @@ pub enum HasLinkResult { /// Trait for a Web Of Trust. /// Allow to provide other implementations of the `WoT` logic instead of the legacy C++ /// translated one. -pub trait WebOfTrust: Clone + Sync { +pub trait WebOfTrust: Clone + Debug + Default + DeserializeOwned + Send + Serialize + Sync { /// Create a new Web of Trust with the maximum of links a node can issue. fn new(max_links: usize) -> Self; diff --git a/wotb/data/rusty.rs b/wotb/data/rusty.rs index 85eefdd324172d7242085965eaa7dbd615c1a08d..22cdd86612fa5e8fd2e51d02f17195572e1844a7 100644 --- a/wotb/data/rusty.rs +++ b/wotb/data/rusty.rs @@ -22,7 +22,7 @@ use NodeId; use WebOfTrust; /// A node in the `WoT` graph. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] struct Node { /// Is this node enabled ? enabled: bool, @@ -44,7 +44,7 @@ impl Node { } /// A more idiomatic implementation of a Web of Trust. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct RustyWebOfTrust { /// List of nodes in the WoT. nodes: Vec<Node>, @@ -52,6 +52,15 @@ pub struct RustyWebOfTrust { max_links: usize, } +impl Default for RustyWebOfTrust { + fn default() -> RustyWebOfTrust { + RustyWebOfTrust { + nodes: Vec::new(), + max_links: 4_000_000_000, + } + } +} + impl WebOfTrust for RustyWebOfTrust { fn new(max_links: usize) -> RustyWebOfTrust { RustyWebOfTrust { diff --git a/wotb/operations/file.rs b/wotb/operations/file.rs index 0f83673dbfa83962f210d8d96c34ee435efdcd2e..515fddaf4cbab33bf1ecae4731b5a277646d3240 100644 --- a/wotb/operations/file.rs +++ b/wotb/operations/file.rs @@ -116,6 +116,14 @@ impl FileFormater for BinaryFileFormater { // Read up to nodes_states_size bytes (nodes_states) let file_pointing_to_links = file_pointing_to_nodes_states.split_off(nodes_states_size as usize); + let count_total_bytes_read = file_pointing_to_links.len() + + nodes_states_size as usize + + 4 + + blockstamp_size as usize + + 4; + if count_total_bytes_read != file_size as usize { + panic!("not read all wot file !"); + } // Apply nodes state let mut count_remaining_nodes = nodes_count; for byte in file_pointing_to_nodes_states { @@ -159,6 +167,9 @@ impl FileFormater for BinaryFileFormater { count_bytes += 1; } } + if count_bytes % 3 != 0 { + panic!("not read all wot file !"); + } Ok((wot, file_pointing_to_blockstamp)) } @@ -182,7 +193,7 @@ impl FileFormater for BinaryFileFormater { let mut bytes: Vec<u8> = Vec::with_capacity(4); bytes.write_u32::<BigEndian>(nodes_count).unwrap(); buffer.append(&mut bytes); - // Write enable state by groups of 8 (count links at the same time) + // Write enable state by groups of 8 let mut enable_states: u8 = 0; let mut factor: u8 = 128; for n in 0..nodes_count {