From 71eb99c0b563d71c2fdc3cf090f89ec24d0722aa Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Fri, 18 May 2018 14:35:50 +0200
Subject: [PATCH] refactor block format (integrate compact document)
---
blockchain/lib.rs | 406 ++++++------------
blockchain/stack_up_block.rs | 178 ++++++++
blockchain/sync.rs | 68 +--
dal/block.rs | 29 +-
dal/identity.rs | 80 ++--
dal/lib.rs | 13 +-
dal/parsers/blocks.rs | 46 +-
dal/parsers/certifications.rs | 72 +++-
dal/parsers/revoked.rs | 53 ++-
dal/writers/block.rs | 7 +-
dal/writers/certification.rs | 19 +-
dal/writers/identity.rs | 5 +-
dal/writers/mod.rs | 1 +
dal/writers/requests.rs | 83 ++++
documents/blockchain/v10/documents/block.rs | 38 +-
.../blockchain/v10/documents/certification.rs | 52 ++-
.../blockchain/v10/documents/identity.rs | 25 +-
.../blockchain/v10/documents/membership.rs | 25 +-
documents/blockchain/v10/documents/mod.rs | 52 ++-
.../blockchain/v10/documents/revocation.rs | 41 +-
.../blockchain/v10/documents/transaction.rs | 27 +-
network/lib.rs | 6 -
ws2p/lib.rs | 18 +-
23 files changed, 841 insertions(+), 503 deletions(-)
create mode 100644 blockchain/stack_up_block.rs
create mode 100644 dal/writers/requests.rs
diff --git a/blockchain/lib.rs b/blockchain/lib.rs
index 7e24de3f..8710a521 100644
--- a/blockchain/lib.rs
+++ b/blockchain/lib.rs
@@ -37,6 +37,7 @@ extern crate serde;
extern crate serde_json;
extern crate sqlite;
+mod stack_up_block;
mod sync;
use std::collections::HashMap;
@@ -47,6 +48,7 @@ use std::str;
use std::sync::mpsc;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
+use self::stack_up_block::try_stack_up_completed_block;
use duniter_crypto::keys::ed25519;
use duniter_dal::block::{DALBlock, WotEvent};
use duniter_dal::constants::MAX_FORKS;
@@ -54,9 +56,8 @@ use duniter_dal::dal_event::DALEvent;
use duniter_dal::dal_requests::{DALReqBlockchain, DALRequest, DALResBlockchain, DALResponse};
use duniter_dal::identity::DALIdentity;
use duniter_dal::parsers::memberships::MembershipParseError;
-use duniter_dal::writers::certification::write_certification;
+use duniter_dal::writers::requests::DBWriteRequest;
use duniter_dal::{DuniterDB, ForkState};
-use duniter_documents::blockchain::v10::documents::membership::MembershipType;
use duniter_documents::blockchain::v10::documents::{BlockDocument, V10Document};
use duniter_documents::blockchain::{BlockchainProtocol, Document, VerificationResult};
use duniter_documents::{BlockHash, BlockId, Blockstamp};
@@ -446,25 +447,27 @@ impl BlockchainModule {
"stackable_block : block {} chainable !",
block_doc.blockstamp()
);
- let (success, wot_events) = match block {
+ let (success, db_requests, wot_events) = match block {
&Block::NetworkBlock(network_block) => self.try_stack_up_block(
&network_block,
wotb_index,
wot,
SyncVerificationLevel::Cautious(),
),
- &Block::LocalBlock(block_doc) => self.try_stack_up_completed_block(
- &block_doc,
- wotb_index,
- wot,
- SyncVerificationLevel::Cautious(),
- ),
+ &Block::LocalBlock(block_doc) => {
+ try_stack_up_completed_block(&block_doc, wotb_index, wot)
+ }
};
debug!(
"stackable_block_ : block {} chainable !",
block_doc.blockstamp()
);
if success {
+ // Apply db requests
+ db_requests
+ .iter()
+ .map(|req| req.apply(&block_doc.currency, &self.db))
+ .collect::<()>();
info!("StackUpValidBlock({})", block_doc.number.0);
self.send_event(DALEvent::StackUpValidBlock(Box::new(block_doc.clone())));
return (true, Vec::with_capacity(0), wot_events);
@@ -491,11 +494,7 @@ impl BlockchainModule {
},
) {
Some(fork) => if forks.len() > fork {
- if fork > 0 {
- (fork, forks[fork])
- } else {
- panic!("fork must be positive !")
- }
+ (fork, forks[fork])
} else {
panic!(format!("Error: fork n° {} is indicated as non-existent whereas it exists in database !", fork));
},
@@ -534,9 +533,6 @@ impl BlockchainModule {
&network_block_v10.uncompleted_block_doc,
fork,
isolate,
- &network_block_v10.joiners,
- &network_block_v10.actives,
- &network_block_v10.leavers,
&network_block_v10.revoked,
&network_block_v10.certifications,
)
@@ -563,265 +559,17 @@ impl BlockchainModule {
wotb_index: &HashMap<ed25519::PublicKey, NodeId>,
wot: &W,
verif_level: SyncVerificationLevel,
- ) -> (bool, Vec<WotEvent>) {
- let block_doc =
- match self.complete_network_block(network_block, wotb_index, verif_level.clone()) {
- Ok(block_doc) => block_doc,
- Err(_) => return (false, Vec::with_capacity(0)),
- };
- self.try_stack_up_completed_block::<W>(&block_doc, wotb_index, wot, verif_level)
- }
- fn complete_network_block(
- &self,
- network_block: &NetworkBlock,
- wotb_index: &HashMap<ed25519::PublicKey, NodeId>,
- verif_level: SyncVerificationLevel,
- ) -> Result<BlockDocument, CompletedBlockError> {
- let db = &self.db;
- if let &NetworkBlock::V10(ref network_block_v10) = network_block {
- let mut block_doc = network_block_v10.uncompleted_block_doc.clone();
- // Indexing block_identities
- let mut block_identities = HashMap::new();
- block_doc
- .identities
- .iter()
- .map(|idty| {
- if idty.issuers().is_empty() {
- panic!("idty without issuer !")
- }
- block_identities.insert(idty.issuers()[0], idty.clone());
- })
- .collect::<()>();
- /*for idty in block_doc.clone().identities {
- if idty.issuers().is_empty() {
- panic!("idty without issuer !")
- }
- block_identities.insert(idty.issuers()[0], idty);
- }*/
- for joiner in duniter_dal::parsers::memberships::parse_memberships_from_json_value(
- &self.currency.to_string(),
- MembershipType::In(),
- &network_block_v10.joiners,
- ) {
- block_doc.joiners.push(joiner?);
- }
- for active in duniter_dal::parsers::memberships::parse_memberships_from_json_value(
- &self.currency.to_string(),
- MembershipType::In(),
- &network_block_v10.actives,
- ) {
- block_doc.actives.push(active?);
- }
- for leaver in duniter_dal::parsers::memberships::parse_memberships_from_json_value(
- &self.currency.to_string(),
- MembershipType::Out(),
- &network_block_v10.leavers,
- ) {
- block_doc.leavers.push(leaver?);
- }
- block_doc.certifications =
- duniter_dal::parsers::certifications::parse_certifications_from_json_value(
- &self.currency.to_string(),
- db,
- &wotb_index,
- &block_identities,
- &network_block_v10.certifications,
- );
- block_doc.revoked = duniter_dal::parsers::revoked::parse_revocations_from_json_value(
- &self.currency.to_string(),
- db,
- &wotb_index,
- &block_identities,
- &network_block_v10.revoked,
- );
- // In cautions mode, verify all signatures !
- if verif_level == SyncVerificationLevel::Cautious() {
- for idty in block_doc.clone().identities {
- if idty.verify_signatures() != VerificationResult::Valid() {
- error!(
- "Fail to sync block #{} : Idty with invalid singature !",
- block_doc.number
- );
- panic!("Idty with invalid singature !");
- }
- }
- }
- let inner_hash = block_doc.inner_hash.expect("BlockchainModule : complete_network_block() : fatal error : block.inner_hash = None");
- if block_doc.number.0 > 0 {
- block_doc.compute_inner_hash();
- }
- let hash = block_doc.hash;
- block_doc.compute_hash();
- if block_doc.inner_hash.expect("BlockchainModule : complete_network_block() : fatal error : block.inner_hash = None") == inner_hash {
- let nonce = block_doc.nonce;
- block_doc.change_nonce(nonce);
- if verif_level == SyncVerificationLevel::FastSync()
- || block_doc.verify_signatures() == VerificationResult::Valid()
- || block_doc.number.0 <= 1 {
- if block_doc.hash == hash {
- Ok(block_doc)
- } else {
- warn!("BlockchainModule : Refuse Bloc : invalid hash !");
- Err(CompletedBlockError::InvalidHash())
- }
- } else {
- warn!("BlockchainModule : Refuse Bloc : invalid signature !");
- Err(CompletedBlockError::InvalidSig())
- }
- } else {
- warn!("BlockchainModule : Refuse Bloc : invalid inner hash !");
- Err(CompletedBlockError::InvalidInnerHash())
- }
- } else {
- Err(CompletedBlockError::InvalidVersion())
- }
- }
- fn try_stack_up_completed_block<W: WebOfTrust + Sync>(
- &self,
- block: &BlockDocument,
- wotb_index: &HashMap<ed25519::PublicKey, NodeId>,
- wot: &W,
- _verif_level: SyncVerificationLevel,
- ) -> (bool, Vec<WotEvent>) {
- debug!(
- "BlockchainModule : try stack up block {}",
- block.blockstamp()
- );
- let db = &self.db;
- let mut wot_events = Vec::new();
- let mut wot_copy: W = wot.clone();
- let mut wotb_index_copy: HashMap<ed25519::PublicKey, NodeId> = wotb_index.clone();
- let current_blockstamp = block.blockstamp();
- let mut identities = HashMap::with_capacity(block.identities.len());
- for identity in block.identities.clone() {
- identities.insert(identity.issuers()[0], identity);
- }
- for joiner in block.joiners.clone() {
- let pubkey = joiner.clone().issuers()[0];
- if let Some(compact_idty) = identities.get(&pubkey) {
- // Newcomer
- let wotb_id = NodeId(wot_copy.size());
- wot_events.push(WotEvent::AddNode(pubkey, wotb_id));
- wot_copy.add_node();
- wotb_index_copy.insert(pubkey, wotb_id);
- let idty = DALIdentity::create_identity(
- db,
- wotb_id,
- compact_idty,
- current_blockstamp.clone(),
- );
- duniter_dal::writers::identity::write(
- &idty,
- db,
- current_blockstamp.clone(),
- block.median_time,
- );
- } else {
- // Renewer
- let wotb_id = wotb_index_copy[&joiner.issuers()[0]];
- wot_events.push(WotEvent::EnableNode(wotb_id));
- wot_copy.set_enabled(wotb_id, true);
- let mut idty =
- DALIdentity::get_identity(&self.currency.to_string(), db, &wotb_id).unwrap();
- idty.renewal_identity(
- db,
- &wotb_index_copy,
- &block.blockstamp(),
- block.median_time,
- false,
- );
- }
- }
- for active in block.actives.clone() {
- let wotb_id = wotb_index_copy[&active.issuers()[0]];
- wot_events.push(WotEvent::EnableNode(wotb_id));
- wot_copy.set_enabled(wotb_id, true);
- let mut idty =
- DALIdentity::get_identity(&self.currency.to_string(), db, &wotb_id).unwrap();
- idty.renewal_identity(
- db,
- &wotb_index_copy,
- &block.blockstamp(),
- block.median_time,
- false,
- );
- }
- for exclusion in block.excluded.clone() {
- let wotb_id = wotb_index_copy[&exclusion];
- wot_events.push(WotEvent::DisableNode(wotb_id));
- wot_copy.set_enabled(wotb_id, false);
- DALIdentity::exclude_identity(db, wotb_id, block.blockstamp(), false);
- }
- for revocation in block.revoked.clone() {
- let wotb_id = wotb_index_copy[&revocation.issuers()[0]];
- wot_events.push(WotEvent::DisableNode(wotb_id));
- wot_copy.set_enabled(wotb_id, false);
- DALIdentity::revoke_identity(db, wotb_id, &block.blockstamp(), false);
- }
- for certification in block.certifications.clone() {
- let wotb_node_from = wotb_index_copy[&certification.issuers()[0]];
- let wotb_node_to = wotb_index_copy[&certification.target()];
- wot_events.push(WotEvent::AddLink(wotb_node_from, wotb_node_to));
- wot_copy.add_link(wotb_node_from, wotb_node_to);
- write_certification(
- &certification,
- db,
- current_blockstamp.clone(),
- block.median_time,
- );
- }
-
- /*// Calculate the state of the wot
- if !wot_events.is_empty() && verif_level != SyncVerificationLevel::FastSync() {
- // Calculate sentries_count
- let sentries_count = wot_copy.get_sentries(3).len();
- // Calculate average_density
- let average_density = calculate_average_density::<W>(&wot_copy);
- let sentry_requirement =
- get_sentry_requirement(block.members_count, G1_PARAMS.step_max);
- // Calculate distances and connectivities
- let (average_distance, distances, average_connectivity, connectivities) =
- compute_distances::<W>(
- &wot_copy,
- sentry_requirement,
- G1_PARAMS.step_max,
- G1_PARAMS.x_percent,
- );
- // Calculate centralities and average_centrality
- let centralities =
- calculate_distance_stress_centralities::<W>(&wot_copy, G1_PARAMS.step_max);
- let average_centrality =
- (centralities.iter().sum::<u64>() as f64 / centralities.len() as f64) as usize;
- // Register the state of the wot
- duniter_dal::register_wot_state(
- db,
- &WotState {
- block_number: block.number.0,
- block_hash: block.hash.unwrap().to_string(),
- sentries_count,
- average_density,
- average_distance,
- distances,
- average_connectivity,
- connectivities: connectivities
- .iter()
- .map(|c| {
- if *c > *G1_CONNECTIVITY_MAX {
- *G1_CONNECTIVITY_MAX
- } else {
- *c
- }
- })
- .collect(),
- average_centrality,
- centralities,
- },
- );
- }*/
- // Write block in bdd
- duniter_dal::writers::block::write(db, block, 0, false);
-
- (true, wot_events)
+ ) -> (bool, Vec<DBWriteRequest>, Vec<WotEvent>) {
+ let block_doc = match complete_network_block(
+ &self.currency.to_string(),
+ Some(&self.db),
+ network_block,
+ verif_level.clone(),
+ ) {
+ Ok(block_doc) => block_doc,
+ Err(_) => return (false, Vec::with_capacity(0), Vec::with_capacity(0)),
+ };
+ try_stack_up_completed_block::<W>(&block_doc, wotb_index, wot)
}
/// Start blockchain module.
pub fn start_blockchain(&mut self, blockchain_receiver: mpsc::Receiver<DuniterMessage>) -> () {
@@ -926,7 +674,6 @@ impl BlockchainModule {
if let Some(current_block) = DALBlock::get_block(
&self.currency.to_string(),
&self.db,
- &wotb_index,
¤t_blockstamp,
) {
debug!("BlockchainModule : send_req_response(CurrentBlock({}))", current_block.block.blockstamp());
@@ -1052,7 +799,6 @@ impl BlockchainModule {
let stackable_blocks = duniter_dal::block::DALBlock::get_stackables_blocks(
&self.currency.to_string(),
&self.db,
- &wotb_index,
¤t_blockstamp,
);
if stackable_blocks.is_empty() {
@@ -1154,3 +900,107 @@ impl BlockchainModule {
}
}
}
+
+/// Complete Network Block
+pub fn complete_network_block(
+ currency: &str,
+ db: Option<&DuniterDB>,
+ network_block: &NetworkBlock,
+ verif_level: SyncVerificationLevel,
+) -> Result<BlockDocument, CompletedBlockError> {
+ if let &NetworkBlock::V10(ref network_block_v10) = network_block {
+ let mut block_doc = network_block_v10.uncompleted_block_doc.clone();
+ trace!("complete_network_block #{}...", block_doc.number);
+ if verif_level == SyncVerificationLevel::Cautious() {
+ // Indexing block_identities
+ let mut block_identities = HashMap::new();
+ block_doc
+ .identities
+ .iter()
+ .map(|idty| {
+ if idty.issuers().is_empty() {
+ panic!("idty without issuer !")
+ }
+ block_identities.insert(idty.issuers()[0], idty.clone());
+ })
+ .collect::<()>();
+ block_doc.certifications =
+ duniter_dal::parsers::certifications::parse_certifications_from_json_value(
+ currency,
+ db.expect("complete_network_block() : Cautious mode need access to blockchain database !"),
+ &block_identities,
+ &network_block_v10.certifications,
+ );
+ trace!("Success to complete certs.");
+ block_doc.revoked = duniter_dal::parsers::revoked::parse_revocations_from_json_value(
+ currency,
+ db.expect(
+ "complete_network_block() : Cautious mode need access to blockchain database !",
+ ),
+ &block_identities,
+ &network_block_v10.revoked,
+ );
+ } else {
+ block_doc.certifications =
+ duniter_dal::parsers::certifications::parse_certifications_into_compact(
+ &network_block_v10.certifications,
+ );
+ trace!("Success to complete certs.");
+ block_doc.revoked = duniter_dal::parsers::revoked::parse_revocations_into_compact(
+ &network_block_v10.revoked,
+ );
+ }
+ trace!("Success to complete certs & revocations.");
+ // In cautions mode, verify all signatures !
+ if verif_level == SyncVerificationLevel::Cautious() {
+ for idty in block_doc.clone().identities {
+ if idty.verify_signatures() != VerificationResult::Valid() {
+ error!(
+ "Fail to sync block #{} : Idty with invalid singature !",
+ block_doc.number
+ );
+ panic!("Idty with invalid singature !");
+ }
+ }
+ }
+ let inner_hash = block_doc.inner_hash.expect(
+ "BlockchainModule : complete_network_block() : fatal error : block.inner_hash = None",
+ );
+ if block_doc.number.0 > 0 {
+ block_doc.compute_inner_hash();
+ }
+ let hash = block_doc.hash;
+ block_doc.compute_hash();
+ if block_doc.inner_hash.expect(
+ "BlockchainModule : complete_network_block() : fatal error : block.inner_hash = None",
+ ) == inner_hash
+ {
+ let nonce = block_doc.nonce;
+ block_doc.change_nonce(nonce);
+ if verif_level == SyncVerificationLevel::FastSync()
+ || block_doc.verify_signatures() == VerificationResult::Valid()
+ || block_doc.number.0 <= 1
+ {
+ if block_doc.hash == hash {
+ trace!("Succes to complete_network_block #{}", block_doc.number.0);
+ Ok(block_doc)
+ } else {
+ warn!("BlockchainModule : Refuse Bloc : invalid hash !");
+ Err(CompletedBlockError::InvalidHash())
+ }
+ } else {
+ warn!("BlockchainModule : Refuse Bloc : invalid signature !");
+ Err(CompletedBlockError::InvalidSig())
+ }
+ } else {
+ warn!("BlockchainModule : Refuse Bloc : invalid inner hash !");
+ debug!(
+ "BlockInnerFormat={}",
+ block_doc.generate_compact_inner_text()
+ );
+ Err(CompletedBlockError::InvalidInnerHash())
+ }
+ } else {
+ Err(CompletedBlockError::InvalidVersion())
+ }
+}
diff --git a/blockchain/stack_up_block.rs b/blockchain/stack_up_block.rs
new file mode 100644
index 00000000..bcc7b15d
--- /dev/null
+++ b/blockchain/stack_up_block.rs
@@ -0,0 +1,178 @@
+// 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/>.
+
+extern crate duniter_crypto;
+extern crate duniter_dal;
+extern crate duniter_documents;
+extern crate duniter_wotb;
+
+use duniter_crypto::keys::ed25519;
+use duniter_dal::block::{DALBlock, WotEvent};
+use duniter_dal::writers::requests::DBWriteRequest;
+use duniter_documents::blockchain::v10::documents::BlockDocument;
+use duniter_documents::blockchain::Document;
+use duniter_wotb::{NodeId, WebOfTrust};
+
+use std::collections::HashMap;
+
+pub fn try_stack_up_completed_block<W: WebOfTrust + Sync>(
+ block: &BlockDocument,
+ wotb_index: &HashMap<ed25519::PublicKey, NodeId>,
+ wot: &W,
+) -> (bool, Vec<DBWriteRequest>, Vec<WotEvent>) {
+ debug!(
+ "BlockchainModule : try stack up complete block {}",
+ block.blockstamp()
+ );
+ let mut db_requests = Vec::new();
+ let mut wot_events = Vec::new();
+ let mut wot_copy: W = wot.clone();
+ let mut wotb_index_copy: HashMap<ed25519::PublicKey, NodeId> = wotb_index.clone();
+ let current_blockstamp = block.blockstamp();
+ let mut identities = HashMap::with_capacity(block.identities.len());
+ for identity in block.identities.clone() {
+ identities.insert(identity.issuers()[0], identity);
+ }
+ for joiner in block.joiners.clone() {
+ let pubkey = joiner.clone().issuers()[0];
+ if let Some(idty_doc) = identities.get(&pubkey) {
+ // Newcomer
+ let wotb_id = NodeId(wot_copy.size());
+ wot_events.push(WotEvent::AddNode(pubkey, wotb_id));
+ wot_copy.add_node();
+ wotb_index_copy.insert(pubkey, wotb_id);
+ db_requests.push(DBWriteRequest::CreateIdentity(
+ wotb_id,
+ current_blockstamp.clone(),
+ block.median_time,
+ idty_doc.clone(),
+ ));
+ } else {
+ // Renewer
+ let wotb_id = wotb_index_copy[&joiner.issuers()[0]];
+ wot_events.push(WotEvent::EnableNode(wotb_id));
+ wot_copy.set_enabled(wotb_id, true);
+ db_requests.push(DBWriteRequest::RenewalIdentity(
+ joiner.issuers()[0],
+ block.blockstamp(),
+ block.median_time,
+ ));
+ }
+ }
+ for active in block.actives.clone() {
+ let pubkey = active.issuers()[0];
+ if !identities.contains_key(&pubkey) {
+ let wotb_id = wotb_index_copy[&pubkey];
+ wot_events.push(WotEvent::EnableNode(wotb_id));
+ wot_copy.set_enabled(wotb_id, true);
+ db_requests.push(DBWriteRequest::RenewalIdentity(
+ pubkey,
+ block.blockstamp(),
+ block.median_time,
+ ));
+ }
+ }
+ for exclusion in block.excluded.clone() {
+ let wotb_id = wotb_index_copy[&exclusion];
+ wot_events.push(WotEvent::DisableNode(wotb_id));
+ wot_copy.set_enabled(wotb_id, false);
+ db_requests.push(DBWriteRequest::ExcludeIdentity(
+ wotb_id,
+ block.blockstamp(),
+ block.median_time,
+ ));
+ }
+ for revocation in block.revoked.clone() {
+ let compact_revoc = revocation.to_compact_document();
+ let wotb_id = wotb_index_copy[&compact_revoc.issuer];
+ wot_events.push(WotEvent::DisableNode(wotb_id));
+ wot_copy.set_enabled(wotb_id, false);
+ db_requests.push(DBWriteRequest::RevokeIdentity(
+ wotb_id,
+ block.blockstamp(),
+ block.median_time,
+ ));
+ }
+ for certification in block.certifications.clone() {
+ trace!("try_stack_up_completed_block: apply cert...");
+ let compact_cert = certification.to_compact_document();
+ let wotb_node_from = wotb_index_copy[&compact_cert.issuer];
+ let wotb_node_to = wotb_index_copy[&compact_cert.target];
+ wot_events.push(WotEvent::AddLink(wotb_node_from, wotb_node_to));
+ wot_copy.add_link(wotb_node_from, wotb_node_to);
+ db_requests.push(DBWriteRequest::CreateCert(
+ block.blockstamp(),
+ block.median_time,
+ compact_cert,
+ ));
+ trace!("try_stack_up_completed_block: apply cert...success.");
+ }
+
+ /*// Calculate the state of the wot
+ if !wot_events.is_empty() && verif_level != SyncVerificationLevel::FastSync() {
+ // Calculate sentries_count
+ let sentries_count = wot_copy.get_sentries(3).len();
+ // Calculate average_density
+ let average_density = calculate_average_density::<W>(&wot_copy);
+ let sentry_requirement =
+ get_sentry_requirement(block.members_count, G1_PARAMS.step_max);
+ // Calculate distances and connectivities
+ let (average_distance, distances, average_connectivity, connectivities) =
+ compute_distances::<W>(
+ &wot_copy,
+ sentry_requirement,
+ G1_PARAMS.step_max,
+ G1_PARAMS.x_percent,
+ );
+ // Calculate centralities and average_centrality
+ let centralities =
+ calculate_distance_stress_centralities::<W>(&wot_copy, G1_PARAMS.step_max);
+ let average_centrality =
+ (centralities.iter().sum::<u64>() as f64 / centralities.len() as f64) as usize;
+ // Register the state of the wot
+ duniter_dal::register_wot_state(
+ db,
+ &WotState {
+ block_number: block.number.0,
+ block_hash: block.hash.unwrap().to_string(),
+ sentries_count,
+ average_density,
+ average_distance,
+ distances,
+ average_connectivity,
+ connectivities: connectivities
+ .iter()
+ .map(|c| {
+ if *c > *G1_CONNECTIVITY_MAX {
+ *G1_CONNECTIVITY_MAX
+ } else {
+ *c
+ }
+ })
+ .collect(),
+ average_centrality,
+ centralities,
+ },
+ );
+ }*/
+ // Write block in bdd
+ db_requests.push(DBWriteRequest::WriteBlock(DALBlock {
+ block: block.clone(),
+ fork: 0,
+ isolate: false,
+ }));
+
+ (true, db_requests, wot_events)
+}
diff --git a/blockchain/sync.rs b/blockchain/sync.rs
index 4646b23e..3fc1000d 100644
--- a/blockchain/sync.rs
+++ b/blockchain/sync.rs
@@ -29,6 +29,8 @@ use self::pbr::ProgressBar;
use duniter_crypto::keys::{ed25519, PublicKey, Signature};
use duniter_dal::parsers::identities::parse_compact_identity;
use duniter_dal::parsers::transactions::parse_transaction;
+//use duniter_dal::writers::requests::DBWriteRequest;
+use duniter_documents::blockchain::v10::documents::membership::MembershipType;
use duniter_documents::blockchain::v10::documents::BlockDocument;
use duniter_documents::{BlockHash, BlockId, Hash};
use duniter_network::{NetworkBlock, NetworkBlockV10};
@@ -51,6 +53,7 @@ pub struct BlockHeader {
enum ParserWorkMess {
TargetBlockstamp(Blockstamp),
NetworkBlock(NetworkBlock),
+ //DBWriteRequest(DBWriteRequest),
End(),
}
@@ -102,8 +105,8 @@ pub fn sync_ts(
info!("Start cautious sync...");
SyncVerificationLevel::Cautious()
} else {
- println!("Start cautious sync...");
- info!("Start cautious sync...");
+ println!("Start fast sync...");
+ info!("Start fast sync...");
SyncVerificationLevel::FastSync()
};
@@ -244,8 +247,21 @@ pub fn sync_ts(
// Apply blocks
while let Ok(ParserWorkMess::NetworkBlock(network_block)) = recv_sync_thread.recv() {
+ // Complete block
+ let block_doc = match complete_network_block(
+ &blockchain_module.currency.to_string(),
+ None,
+ &network_block,
+ SyncVerificationLevel::FastSync(),
+ ) {
+ Ok(block_doc) => block_doc,
+ Err(_) => panic!("Receive wrong block, please reset data and resync !"),
+ };
// Apply block
- let (success, new_wot_events) = blockchain_module.try_stack_up_block::<RustyWebOfTrust>(
+ let (success, db_requests, new_wot_events) =
+ try_stack_up_completed_block::<RustyWebOfTrust>(&block_doc, &wotb_index, &wot);
+
+ blockchain_module.try_stack_up_block::<RustyWebOfTrust>(
&network_block,
&wotb_index,
&wot,
@@ -253,6 +269,13 @@ pub fn sync_ts(
);
if success {
current_blockstamp = network_block.blockstamp();
+ debug!("Apply db requests...");
+ // Apply db requests
+ db_requests
+ .iter()
+ .map(|req| req.apply(&conf.currency().to_string(), &blockchain_module.db))
+ .collect::<()>();
+ debug!("Finish to apply db requests.");
// Apply WotEvents
if !new_wot_events.is_empty() {
for wot_event in new_wot_events {
@@ -430,9 +453,21 @@ pub fn parse_ts_block(row: &[sqlite::Value]) -> NetworkBlock {
),
dividend: dividend,
identities,
- joiners: Vec::new(),
- actives: Vec::new(),
- leavers: Vec::new(),
+ joiners: duniter_dal::parsers::memberships::parse_memberships(
+ currency,
+ MembershipType::In(),
+ row[21].as_string().expect("Fail to parse joiners"),
+ ).expect("Fail to parse joiners (2)"),
+ actives: duniter_dal::parsers::memberships::parse_memberships(
+ currency,
+ MembershipType::In(),
+ row[22].as_string().expect("Fail to parse actives"),
+ ).expect("Fail to parse actives (2)"),
+ leavers: duniter_dal::parsers::memberships::parse_memberships(
+ currency,
+ MembershipType::In(),
+ row[23].as_string().expect("Fail to parse leavers"),
+ ).expect("Fail to parse leavers (2)"),
revoked: Vec::new(),
excluded: excluded
.as_array()
@@ -448,15 +483,6 @@ pub fn parse_ts_block(row: &[sqlite::Value]) -> NetworkBlock {
transactions,
inner_hash_and_nonce_str: String::new(),
};
- let joiners: serde_json::Value = serde_json::from_str(
- row[21].as_string().expect("Fail to parse joiners"),
- ).expect("Fail to parse joiners (2)");
- let actives: serde_json::Value = serde_json::from_str(
- row[22].as_string().expect("Fail to parse actives"),
- ).expect("Fail to parse actives (2)");
- let leavers: serde_json::Value = serde_json::from_str(
- row[23].as_string().expect("Fail to parse leavers"),
- ).expect("Fail to parse leavers (2)");
let revoked: serde_json::Value = serde_json::from_str(
row[24].as_string().expect("Fail to parse revoked"),
).expect("Fail to parse revoked (2)");
@@ -466,18 +492,6 @@ pub fn parse_ts_block(row: &[sqlite::Value]) -> NetworkBlock {
// return NetworkBlock
NetworkBlock::V10(Box::new(NetworkBlockV10 {
uncompleted_block_doc,
- joiners: joiners
- .as_array()
- .expect("Fail to parse joiners (3)")
- .to_vec(),
- actives: actives
- .as_array()
- .expect("Fail to parse actives (3)")
- .to_vec(),
- leavers: leavers
- .as_array()
- .expect("Fail to parse leavers (3)")
- .to_vec(),
revoked: revoked
.as_array()
.expect("Fail to parse revoked (3)")
diff --git a/dal/block.rs b/dal/block.rs
index 92d5cefd..ae29b95d 100644
--- a/dal/block.rs
+++ b/dal/block.rs
@@ -79,8 +79,6 @@ pub struct DALBlock {
pub fork: usize,
pub isolate: bool,
pub block: BlockDocument,
- pub median_frame: usize,
- pub second_tiercile_frame: usize,
}
impl DALBlock {
@@ -195,7 +193,6 @@ impl DALBlock {
pub fn get_stackables_blocks(
currency: &str,
db: &DuniterDB,
- wotb_index: &HashMap<ed25519::PublicKey, NodeId>,
current_blockstamp: &Blockstamp,
) -> Vec<DALBlock> {
debug!("get_stackables_blocks() after {}", current_blockstamp);
@@ -204,12 +201,9 @@ impl DALBlock {
let (hashs, previous_hashs) = DALBlock::get_blocks_hashs_all_forks(db, &block_id);
for (hash, previous_hash) in hashs.into_iter().zip(previous_hashs) {
if previous_hash == current_blockstamp.hash.0 {
- if let Some(dal_block) = DALBlock::get_block(
- currency,
- db,
- wotb_index,
- &Blockstamp { id: block_id, hash },
- ) {
+ if let Some(dal_block) =
+ DALBlock::get_block(currency, db, &Blockstamp { id: block_id, hash })
+ {
stackables_blocks.push(dal_block);
} else {
panic!(format!(
@@ -237,12 +231,7 @@ impl DALBlock {
}
stackables_forks
}
- pub fn get_block(
- currency: &str,
- db: &DuniterDB,
- wotb_index: &HashMap<ed25519::PublicKey, NodeId>,
- blockstamp: &Blockstamp,
- ) -> Option<DALBlock> {
+ pub fn get_block(currency: &str, db: &DuniterDB, blockstamp: &Blockstamp) -> Option<DALBlock> {
let mut cursor = db
.0
.prepare(
@@ -410,7 +399,6 @@ impl DALBlock {
revoked: parse_revocations(
currency,
db,
- wotb_index,
&hashmap_identities,
row[25]
.as_string()
@@ -424,7 +412,6 @@ impl DALBlock {
certifications: parse_certifications(
currency,
db,
- wotb_index,
&hashmap_identities,
row[27]
.as_string()
@@ -444,8 +431,8 @@ impl DALBlock {
nonce
),
},
- median_frame: row[13].as_integer().unwrap_or(0) as usize,
- second_tiercile_frame: row[14].as_integer().unwrap_or(0) as usize,
+ //median_frame: row[13].as_integer().unwrap_or(0) as usize,
+ //second_tiercile_frame: row[14].as_integer().unwrap_or(0) as usize,
})
} else {
None
@@ -499,7 +486,7 @@ impl DALBlock {
let mut current_frame_vec: Vec<_> = current_frame.values().cloned().collect();
current_frame_vec.sort_unstable();
- // Calculate median
+ /*// Calculate median
let mut median_index = match self.block.issuers_count % 2 {
1 => (self.block.issuers_count / 2) + 1,
_ => self.block.issuers_count / 2,
@@ -517,7 +504,7 @@ impl DALBlock {
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];
+ self.second_tiercile_frame = current_frame_vec[second_tiercile_index];*/
}
}
}
diff --git a/dal/identity.rs b/dal/identity.rs
index b65dc030..2486c628 100644
--- a/dal/identity.rs
+++ b/dal/identity.rs
@@ -12,7 +12,6 @@ use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct DALIdentity {
- pub wotb_id: NodeId,
pub hash: String,
pub state: isize,
pub joined_on: Blockstamp,
@@ -78,7 +77,6 @@ impl DALIdentity {
pub fn create_identity(
db: &DuniterDB,
- wotb_id: NodeId,
idty_doc: &IdentityDocument,
current_blockstamp: Blockstamp,
) -> DALIdentity {
@@ -87,7 +85,6 @@ impl DALIdentity {
.expect("convert blockstamp to timestamp failure !");
DALIdentity {
- wotb_id,
hash: "0".to_string(),
state: 0,
joined_on: current_blockstamp,
@@ -131,7 +128,7 @@ impl DALIdentity {
pub fn renewal_identity(
&mut self,
db: &DuniterDB,
- wotb_index: &HashMap<ed25519::PublicKey, NodeId>,
+ pubkey: &ed25519::PublicKey,
renewal_blockstamp: &Blockstamp,
renawal_timestamp: u64,
revert: bool,
@@ -142,9 +139,8 @@ impl DALIdentity {
DALBlock::get_block(
self.idty_doc.currency(),
db,
- wotb_index,
&self.penultimate_renewed_on.clone(),
- ).unwrap(),
+ ).expect("renewal_identity: Fail to get penultimate_renewed_block"),
);
penultimate_renewed_block.clone().unwrap().block.median_time
+ super::constants::G1_PARAMS.ms_validity < renawal_timestamp
@@ -160,7 +156,7 @@ impl DALIdentity {
};
let mut cursor = db.0
.prepare(
- "UPDATE identities SET state=?, last_renewed_on=?, expires_on=?, revokes_on=? WHERE wotb_id=?;",
+ "UPDATE identities SET state=?, last_renewed_on=?, expires_on=?, revokes_on=? WHERE pubkey=?;",
)
.expect("Fail to renewal idty !")
.cursor();
@@ -173,7 +169,7 @@ impl DALIdentity {
sqlite::Value::Integer(
(renawal_timestamp + (super::constants::G1_PARAMS.ms_validity * 2)) as i64,
),
- sqlite::Value::Integer(self.wotb_id.0 as i64),
+ sqlite::Value::String(pubkey.to_string()),
])
.expect("Fail to renewal idty !");
}
@@ -187,62 +183,92 @@ impl DALIdentity {
.unwrap();
}
- pub fn get_identity(currency: &str, db: &DuniterDB, wotb_id: &NodeId) -> Option<DALIdentity> {
+ pub fn get_identity(
+ currency: &str,
+ db: &DuniterDB,
+ pubkey: &ed25519::PublicKey,
+ ) -> Option<DALIdentity> {
let mut cursor = db
.0
.prepare(
- "SELECT uid, pubkey, hash, sig,
+ "SELECT uid, hash, sig,
state, created_on, joined_on, penultimate_renewed_on, last_renewed_on,
- expires_on, revokes_on, expired_on, revoked_on FROM identities WHERE wotb_id=?;",
+ expires_on, revokes_on, expired_on, revoked_on FROM identities WHERE pubkey=?;",
)
.expect("Fail to get idty !")
.cursor();
cursor
- .bind(&[sqlite::Value::Integer(wotb_id.0 as i64)])
+ .bind(&[sqlite::Value::String(pubkey.to_string())])
.expect("Fail to get idty !");
- if let Some(row) = cursor.next().unwrap() {
+ if let Some(row) = cursor.next().expect("get_identity: cursor error") {
let idty_doc_builder = IdentityDocumentBuilder {
currency,
- username: row[0].as_string().unwrap(),
+ username: row[0]
+ .as_string()
+ .expect("get_identity: fail to parse username"),
blockstamp: &Blockstamp::from_string(
- row[5]
+ row[4]
.as_string()
.expect("DB Error : idty created_on invalid !"),
).expect("DB Error : idty created_on invalid (2) !"),
- issuer: &PublicKey::from_base58(row[1].as_string().unwrap()).unwrap(),
+ issuer: &pubkey,
};
- let idty_sig = Signature::from_base64(row[3].as_string().unwrap()).unwrap();
+ let idty_sig = Signature::from_base64(
+ row[2].as_string().expect("get_identity: fail to parse sig"),
+ ).expect("get_identity: fail to parse sig (2)");
let idty_doc = idty_doc_builder.build_with_signature(vec![idty_sig]);
- let expired_on = match Blockstamp::from_string(row[11].as_string().unwrap()) {
+ let expired_on = match Blockstamp::from_string(
+ row[10]
+ .as_string()
+ .expect("get_identity: fail to parse expire on"),
+ ) {
Ok(blockstamp) => Some(blockstamp),
Err(_) => None,
};
- let revoked_on = match Blockstamp::from_string(row[12].as_string().unwrap()) {
+ let revoked_on = match Blockstamp::from_string(
+ row[11]
+ .as_string()
+ .expect("get_identity: fail to parse revoked on"),
+ ) {
Ok(blockstamp) => Some(blockstamp),
Err(_) => None,
};
Some(DALIdentity {
- wotb_id: wotb_id.clone(),
- hash: row[2].as_string().unwrap().to_string(),
- state: row[4].as_integer().unwrap() as isize,
+ hash: row[2]
+ .as_string()
+ .expect("get_identity: fail to parse hash")
+ .to_string(),
+ state: row[3]
+ .as_integer()
+ .expect("get_identity: fail to parse state") as isize,
joined_on: Blockstamp::from_string(
- row[6]
+ row[5]
.as_string()
.expect("DB Error : idty joined_on invalid !"),
).expect("DB Error : idty joined_on invalid !"),
penultimate_renewed_on: Blockstamp::from_string(
- row[7]
+ row[6]
.as_string()
.expect("DB Error : idty penultimate_renewed_on invalid !"),
).expect(
"DB Error : idty penultimate_renewed_on invalid (2) !",
),
- last_renewed_on: Blockstamp::from_string(row[8].as_string().unwrap()).unwrap(),
- expires_on: row[9].as_integer().unwrap() as u64,
- revokes_on: row[10].as_integer().unwrap() as u64,
+ last_renewed_on: Blockstamp::from_string(
+ row[7]
+ .as_string()
+ .expect("get_identity: fail to parse last_renewed_on"),
+ ).expect("get_identity: fail to parse last_renewed_on (2)"),
+ expires_on: row[8]
+ .as_integer()
+ .expect("get_identity: fail to parse expires_on")
+ as u64,
+ revokes_on: row[9]
+ .as_integer()
+ .expect("get_identity: fail to parse revokes_on")
+ as u64,
expired_on,
revoked_on,
idty_doc,
diff --git a/dal/lib.rs b/dal/lib.rs
index 7b6eb80e..7c1541dc 100644
--- a/dal/lib.rs
+++ b/dal/lib.rs
@@ -44,11 +44,10 @@ pub mod parsers;
pub mod tools;
pub mod writers;
-use duniter_crypto::keys::{ed25519, PublicKey, Signature};
+use duniter_crypto::keys::{PublicKey, Signature};
use duniter_documents::blockchain::v10::documents::BlockDocument;
use duniter_documents::{BlockHash, BlockId, Blockstamp, Hash};
use duniter_wotb::NodeId;
-use std::collections::HashMap;
use std::fmt::Debug;
use std::marker;
use std::path::PathBuf;
@@ -144,7 +143,7 @@ pub fn close_db(db: &DuniterDB) {
pub fn get_uid(db: &DuniterDB, wotb_id: NodeId) -> Option<String> {
let mut cursor: sqlite::Cursor = db
.0
- .prepare("SELECT uid FROM identities WHERE wotb_id=? LIMIT 1;")
+ .prepare("SELECT uid FROM identities WHERE wotb_id=? AND state=0 LIMIT 1;")
.expect("Request SQL get_current_block is wrong !")
.cursor();
cursor
@@ -217,11 +216,7 @@ pub fn new_get_current_block(db: &DuniterDB) -> Option<BlockDocument> {
None
}
-pub fn get_current_block(
- currency: &str,
- db: &DuniterDB,
- wotb_index: &HashMap<ed25519::PublicKey, NodeId>,
-) -> Option<DALBlock> {
+pub fn get_current_block(currency: &str, db: &DuniterDB) -> Option<DALBlock> {
let mut cursor: sqlite::Cursor = db
.0
.prepare("SELECT number, hash FROM blocks WHERE fork=0 ORDER BY median_time DESC LIMIT ?;")
@@ -235,7 +230,7 @@ pub fn get_current_block(
id: BlockId(row[0].as_integer().unwrap() as u32),
hash: BlockHash(Hash::from_hex(row[1].as_string().unwrap()).unwrap()),
};
- DALBlock::get_block(currency, db, wotb_index, &blockstamp)
+ DALBlock::get_block(currency, db, &blockstamp)
} else {
None
}
diff --git a/dal/parsers/blocks.rs b/dal/parsers/blocks.rs
index e78ce51a..780ff728 100644
--- a/dal/parsers/blocks.rs
+++ b/dal/parsers/blocks.rs
@@ -8,6 +8,7 @@ use super::excluded::parse_exclusions_from_json_value;
use super::identities::parse_compact_identity;
use super::transactions::parse_transaction;
use duniter_crypto::keys::{PublicKey, Signature};
+use duniter_documents::blockchain::v10::documents::membership::MembershipType;
use duniter_documents::blockchain::v10::documents::BlockDocument;
use duniter_documents::{BlockHash, BlockId, Hash};
@@ -60,6 +61,42 @@ pub fn parse_json_block(source: &serde_json::Value) -> Option<NetworkBlock> {
for raw_idty in source.get("identities")?.as_array()? {
identities.push(parse_compact_identity(¤cy, &raw_idty)?);
}
+ let mut joiners = Vec::new();
+ for joiner in super::memberships::parse_memberships_from_json_value(
+ ¤cy,
+ MembershipType::In(),
+ &source.get("joiners")?.as_array()?,
+ ) {
+ if let Ok(joiner) = joiner {
+ joiners.push(joiner);
+ } else {
+ return None;
+ }
+ }
+ let mut actives = Vec::new();
+ for active in super::memberships::parse_memberships_from_json_value(
+ ¤cy,
+ MembershipType::In(),
+ &source.get("actives")?.as_array()?,
+ ) {
+ if let Ok(active) = active {
+ actives.push(active);
+ } else {
+ return None;
+ }
+ }
+ let mut leavers = Vec::new();
+ for leaver in super::memberships::parse_memberships_from_json_value(
+ ¤cy,
+ MembershipType::Out(),
+ &source.get("leavers")?.as_array()?,
+ ) {
+ if let Ok(leaver) = leaver {
+ leavers.push(leaver);
+ } else {
+ return None;
+ }
+ }
let mut transactions = Vec::new();
for json_tx in source.get("transactions")?.as_array()? {
transactions.push(parse_transaction("g1", &json_tx)?);
@@ -86,9 +123,9 @@ pub fn parse_json_block(source: &serde_json::Value) -> Option<NetworkBlock> {
inner_hash,
dividend,
identities,
- joiners: Vec::with_capacity(0),
- actives: Vec::with_capacity(0),
- leavers: Vec::with_capacity(0),
+ joiners,
+ actives,
+ leavers,
revoked: Vec::with_capacity(0),
excluded: parse_exclusions_from_json_value(&source.get("excluded")?.as_array()?),
certifications: Vec::with_capacity(0),
@@ -101,9 +138,6 @@ pub fn parse_json_block(source: &serde_json::Value) -> Option<NetworkBlock> {
};
Some(NetworkBlock::V10(Box::new(NetworkBlockV10 {
uncompleted_block_doc: block_doc,
- joiners: source.get("joiners")?.as_array()?.clone(),
- actives: source.get("actives")?.as_array()?.clone(),
- leavers: source.get("leavers")?.as_array()?.clone(),
revoked: source.get("revoked")?.as_array()?.clone(),
certifications: source.get("certifications")?.as_array()?.clone(),
})))
diff --git a/dal/parsers/certifications.rs b/dal/parsers/certifications.rs
index ee395afd..a62b0a4a 100644
--- a/dal/parsers/certifications.rs
+++ b/dal/parsers/certifications.rs
@@ -6,34 +6,65 @@ use super::super::block::DALBlock;
use super::super::identity::DALIdentity;
use super::super::DuniterDB;
use duniter_crypto::keys::{ed25519, PublicKey, Signature};
-use duniter_documents::blockchain::v10::documents::certification::CertificationDocumentBuilder;
-use duniter_documents::blockchain::v10::documents::{CertificationDocument, IdentityDocument};
+use duniter_documents::blockchain::v10::documents::certification::{
+ CertificationDocumentBuilder, CompactCertificationDocument,
+};
+use duniter_documents::blockchain::v10::documents::{
+ CertificationDocument, IdentityDocument, TextDocumentFormat,
+};
use duniter_documents::blockchain::{Document, DocumentBuilder};
use duniter_documents::{BlockHash, BlockId, Blockstamp, Hash};
-use duniter_wotb::NodeId;
use std::collections::HashMap;
+pub fn parse_certifications_into_compact(
+ json_certs: &Vec<serde_json::Value>,
+) -> Vec<TextDocumentFormat<CertificationDocument>> {
+ let mut certifications: Vec<TextDocumentFormat<CertificationDocument>> = Vec::new();
+ for certification in json_certs.iter() {
+ let certifications_datas: Vec<&str> = certification
+ .as_str()
+ .expect("Receive block in wrong format : fail to split cert !")
+ .split(':')
+ .collect();
+ if certifications_datas.len() == 4 {
+ certifications.push(TextDocumentFormat::Compact(CompactCertificationDocument {
+ issuer: PublicKey::from_base58(certifications_datas[0])
+ .expect("Receive block in wrong format : fail to parse issuer !"),
+ target: PublicKey::from_base58(certifications_datas[1])
+ .expect("Receive block in wrong format : fail to parse target !"),
+ block_number: BlockId(
+ certifications_datas[2]
+ .parse()
+ .expect("Receive block in wrong format : fail to parse block number !"),
+ ),
+ signature: Signature::from_base64(certifications_datas[3])
+ .expect("Receive block in wrong format : fail to parse signature !"),
+ }));
+ }
+ }
+ certifications
+}
+
pub fn parse_certifications_from_json_value(
currency: &str,
db: &DuniterDB,
- wotb_index: &HashMap<ed25519::PublicKey, NodeId>,
block_identities: &HashMap<ed25519::PublicKey, IdentityDocument>,
array_certifications: &[serde_json::Value],
-) -> Vec<CertificationDocument> {
- let mut certifications: Vec<CertificationDocument> = Vec::new();
+) -> Vec<TextDocumentFormat<CertificationDocument>> {
+ let mut certifications: Vec<TextDocumentFormat<CertificationDocument>> = Vec::new();
for certification in array_certifications.iter() {
- let certification_datas: Vec<&str> = certification.as_str().unwrap().split(':').collect();
+ let certification_datas: Vec<&str> = certification
+ .as_str()
+ .expect("Fail to parse certs : json isn't str !")
+ .split(':')
+ .collect();
if certification_datas.len() == 4 {
let target = PublicKey::from_base58(certification_datas[1])
.expect("Fail to parse cert target !");
let target_idty_doc: IdentityDocument = match block_identities.get(&target) {
Some(idty_doc) => idty_doc.clone(),
None => {
- let target_wotb_id = wotb_index.get(&target).expect(&format!(
- "target identity {} not found in wotb index !",
- target.to_string()
- ));
- let dal_idty = DALIdentity::get_identity(currency, db, target_wotb_id)
+ let dal_idty = DALIdentity::get_identity(currency, db, &target)
.expect("target identity not found in bdd !");
dal_idty.idty_doc
}
@@ -53,7 +84,7 @@ pub fn parse_certifications_from_json_value(
hash: if cert_blockstamp_id == BlockId(0) {
BlockHash(Hash::from_hex(
"E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
- ).unwrap())
+ ).expect("Fail to parse cert : invalid genesis hash"))
} else {
DALBlock::get_block_hash(db, &cert_blockstamp_id).expect(&format!(
"Fatal Error : Block {} not found in bdd !",
@@ -68,7 +99,9 @@ pub fn parse_certifications_from_json_value(
};
let cert_sig =
Signature::from_base64(certification_datas[3]).expect("Fail to parse cert sig !");
- certifications.push(cert_builder.build_with_signature(vec![cert_sig]));
+ certifications.push(TextDocumentFormat::Complete(
+ cert_builder.build_with_signature(vec![cert_sig]),
+ ));
}
}
certifications
@@ -77,19 +110,20 @@ pub fn parse_certifications_from_json_value(
pub fn parse_certifications(
currency: &str,
db: &DuniterDB,
- wotb_index: &HashMap<ed25519::PublicKey, NodeId>,
block_identities: &HashMap<ed25519::PublicKey, IdentityDocument>,
json_datas: &str,
-) -> Option<Vec<CertificationDocument>> {
- let raw_certifications: serde_json::Value = serde_json::from_str(json_datas).unwrap();
+) -> Option<Vec<TextDocumentFormat<CertificationDocument>>> {
+ let raw_certifications: serde_json::Value =
+ serde_json::from_str(json_datas).expect("Fail to parse certs: str isn't json !");
if raw_certifications.is_array() {
Some(parse_certifications_from_json_value(
currency,
db,
- wotb_index,
block_identities,
- raw_certifications.as_array().unwrap(),
+ raw_certifications
+ .as_array()
+ .expect("Fail to parse certs: json datas must be an array !"),
))
} else {
None
diff --git a/dal/parsers/revoked.rs b/dal/parsers/revoked.rs
index dc24d1b2..28f12568 100644
--- a/dal/parsers/revoked.rs
+++ b/dal/parsers/revoked.rs
@@ -1,32 +1,55 @@
extern crate serde_json;
use duniter_crypto::keys::{ed25519, PublicKey, Signature};
-use duniter_documents::blockchain::v10::documents::revocation::RevocationDocumentBuilder;
-use duniter_documents::blockchain::v10::documents::{IdentityDocument, RevocationDocument};
+use duniter_documents::blockchain::v10::documents::revocation::{
+ CompactRevocationDocument, RevocationDocumentBuilder,
+};
+use duniter_documents::blockchain::v10::documents::{
+ IdentityDocument, RevocationDocument, TextDocumentFormat,
+};
use duniter_documents::blockchain::{Document, DocumentBuilder};
-use duniter_wotb::NodeId;
use super::super::identity::DALIdentity;
use super::super::DuniterDB;
use std::collections::HashMap;
+pub fn parse_revocations_into_compact(
+ json_recocations: &Vec<serde_json::Value>,
+) -> Vec<TextDocumentFormat<RevocationDocument>> {
+ let mut revocations: Vec<TextDocumentFormat<RevocationDocument>> = Vec::new();
+ for revocation in json_recocations.iter() {
+ let revocations_datas: Vec<&str> = revocation
+ .as_str()
+ .expect("Receive block in wrong format !")
+ .split(':')
+ .collect();
+ if revocations_datas.len() == 2 {
+ revocations.push(TextDocumentFormat::Compact(CompactRevocationDocument {
+ issuer: PublicKey::from_base58(revocations_datas[0])
+ .expect("Receive block in wrong format !"),
+ signature: Signature::from_base64(revocations_datas[1])
+ .expect("Receive block in wrong format !"),
+ }));
+ }
+ }
+ revocations
+}
+
pub fn parse_revocations(
currency: &str,
db: &DuniterDB,
- wotb_index: &HashMap<ed25519::PublicKey, NodeId>,
block_identities: &HashMap<ed25519::PublicKey, IdentityDocument>,
json_datas: &str,
-) -> Option<Vec<RevocationDocument>> {
- let raw_certifications: serde_json::Value = serde_json::from_str(json_datas).unwrap();
+) -> Option<Vec<TextDocumentFormat<RevocationDocument>>> {
+ let raw_revocations: serde_json::Value = serde_json::from_str(json_datas).unwrap();
- if raw_certifications.is_array() {
+ if raw_revocations.is_array() {
Some(parse_revocations_from_json_value(
currency,
db,
- wotb_index,
block_identities,
- raw_certifications.as_array().unwrap(),
+ raw_revocations.as_array().unwrap(),
))
} else {
None
@@ -36,11 +59,10 @@ pub fn parse_revocations(
pub fn parse_revocations_from_json_value(
currency: &str,
db: &DuniterDB,
- wotb_index: &HashMap<ed25519::PublicKey, NodeId>,
block_identities: &HashMap<ed25519::PublicKey, IdentityDocument>,
array_revocations: &[serde_json::Value],
-) -> Vec<RevocationDocument> {
- let mut revocations: Vec<RevocationDocument> = Vec::new();
+) -> Vec<TextDocumentFormat<RevocationDocument>> {
+ let mut revocations: Vec<TextDocumentFormat<RevocationDocument>> = Vec::new();
for revocation in array_revocations.iter() {
let revocations_datas: Vec<&str> = revocation.as_str().unwrap().split(':').collect();
if revocations_datas.len() == 2 {
@@ -49,8 +71,7 @@ pub fn parse_revocations_from_json_value(
let idty_doc: IdentityDocument = match block_identities.get(&idty_pubkey) {
Some(idty_doc) => idty_doc.clone(),
None => {
- let idty_wotb_id = wotb_index.get(&idty_pubkey).unwrap();
- let dal_idty = DALIdentity::get_identity(currency, db, idty_wotb_id).unwrap();
+ let dal_idty = DALIdentity::get_identity(currency, db, &idty_pubkey).unwrap();
dal_idty.idty_doc
}
};
@@ -62,7 +83,9 @@ pub fn parse_revocations_from_json_value(
identity_sig: &idty_doc.signatures()[0],
};
let revoc_sig = Signature::from_base64(revocations_datas[1]).unwrap();
- revocations.push(revoc_doc_builder.build_with_signature(vec![revoc_sig]));
+ revocations.push(TextDocumentFormat::Complete(
+ revoc_doc_builder.build_with_signature(vec![revoc_sig]),
+ ));
}
}
revocations
diff --git a/dal/writers/block.rs b/dal/writers/block.rs
index 906dbdfe..aeb4d4d8 100644
--- a/dal/writers/block.rs
+++ b/dal/writers/block.rs
@@ -15,9 +15,6 @@ pub fn write_network_block(
block: &BlockDocument,
fork: usize,
isolate: bool,
- joiners: &Vec<serde_json::Value>,
- actives: &Vec<serde_json::Value>,
- leavers: &Vec<serde_json::Value>,
revoked: &Vec<serde_json::Value>,
certifications: &Vec<serde_json::Value>,
) {
@@ -32,8 +29,8 @@ pub fn write_network_block(
block.previous_hash.to_string(), block.inner_hash.unwrap().to_string(),
block.dividend.unwrap_or(0),
serde_json::to_string(&block.identities).unwrap(),
- serde_json::to_string(joiners).unwrap(), serde_json::to_string(actives).unwrap(),
- serde_json::to_string(leavers).unwrap(), serde_json::to_string(revoked).unwrap(),
+ serde_json::to_string(&block.joiners).unwrap(), serde_json::to_string(&block.actives).unwrap(),
+ serde_json::to_string(&block.leavers).unwrap(), serde_json::to_string(revoked).unwrap(),
serde_json::to_string(&block.excluded).unwrap(), serde_json::to_string(certifications).unwrap(),
serde_json::to_string(&block.transactions).unwrap()
))
diff --git a/dal/writers/certification.rs b/dal/writers/certification.rs
index 511c7766..03ec2db9 100644
--- a/dal/writers/certification.rs
+++ b/dal/writers/certification.rs
@@ -4,12 +4,11 @@ extern crate sqlite;
use super::super::DuniterDB;
use duniter_crypto::keys::ed25519;
-use duniter_documents::blockchain::v10::documents::CertificationDocument;
-use duniter_documents::blockchain::Document;
+use duniter_documents::blockchain::v10::documents::certification::CompactCertificationDocument;
use duniter_documents::Blockstamp;
pub fn write_certification(
- cert: &CertificationDocument,
+ cert: &CompactCertificationDocument,
db: &DuniterDB,
written_blockstamp: Blockstamp,
written_timestamp: u64,
@@ -17,11 +16,11 @@ pub fn write_certification(
let mut cursor = db
.0
.prepare("SELECT median_time FROM blocks WHERE number=? AND fork=0 LIMIT 1;")
- .unwrap()
+ .expect("invalid write_certification sql request")
.cursor();
cursor
- .bind(&[sqlite::Value::Integer(cert.blockstamp().id.0 as i64)])
+ .bind(&[sqlite::Value::Integer(cert.block_number.0 as i64)])
.expect("convert blockstamp to timestamp failure at step 1 !");
let mut created_timestamp: i64 = 0;
@@ -29,18 +28,20 @@ pub fn write_certification(
.next()
.expect("convert blockstamp to timestamp failure at step 2 !")
{
- created_timestamp = row[0].as_integer().unwrap();
+ created_timestamp = row[0]
+ .as_integer()
+ .expect("Fail to write cert, impossible to get created_timestamp !");
}
db.0
.execute(
format!("INSERT INTO certifications (pubkey_from, pubkey_to, created_on, signature, written_on, expires_on, chainable_on) VALUES ('{}', '{}', '{}', '{}', '{}', {}, {});",
- cert.issuers()[0], cert.target(), cert.blockstamp().id.0, cert.signatures()[0],
+ cert.issuer, cert.target, cert.block_number.0, cert.signature,
written_blockstamp.to_string(),
created_timestamp+super::super::constants::G1_PARAMS.sig_validity,
written_timestamp+super::super::constants::G1_PARAMS.sig_period
))
- .unwrap();
+ .expect("Fail to execute INSERT certification !");
}
pub fn remove_certification(from: ed25519::PublicKey, to: ed25519::PublicKey, db: &DuniterDB) {
@@ -49,5 +50,5 @@ pub fn remove_certification(from: ed25519::PublicKey, to: ed25519::PublicKey, db
"DELETE FROM certifications WHERE pubkey_from={} AND pubkey_to={}",
from, to
))
- .unwrap();
+ .expect("Fail to execute DELETE certification !");
}
diff --git a/dal/writers/identity.rs b/dal/writers/identity.rs
index c000d945..ea106fce 100644
--- a/dal/writers/identity.rs
+++ b/dal/writers/identity.rs
@@ -1,12 +1,15 @@
+extern crate duniter_wotb;
extern crate sqlite;
use super::super::identity::DALIdentity;
use super::super::DuniterDB;
use duniter_documents::blockchain::Document;
use duniter_documents::Blockstamp;
+use duniter_wotb::NodeId;
pub fn write(
idty: &DALIdentity,
+ wotb_id: &NodeId,
db: &DuniterDB,
_written_blockstamp: Blockstamp,
_written_timestamp: u64,
@@ -22,7 +25,7 @@ pub fn write(
db.0
.execute(
format!("INSERT INTO identities (wotb_id, uid, pubkey, hash, sig, state, created_on, joined_on, penultimate_renewed_on, last_renewed_on, expires_on, revokes_on, expired_on, revoked_on) VALUES ({}, '{}', '{}', '{}', '{}', {}, '{}', '{}', '{}', '{}', {}, {}, '{}', '{}');",
- idty.wotb_id.0, idty.idty_doc.username(), idty.idty_doc.issuers()[0], idty.hash,
+ (*wotb_id).0, idty.idty_doc.username(), idty.idty_doc.issuers()[0], idty.hash,
idty.idty_doc.signatures()[0], idty.state,
idty.idty_doc.blockstamp().to_string(),
idty.joined_on.to_string(),
diff --git a/dal/writers/mod.rs b/dal/writers/mod.rs
index 41219969..aba7f800 100644
--- a/dal/writers/mod.rs
+++ b/dal/writers/mod.rs
@@ -1,3 +1,4 @@
pub mod block;
pub mod certification;
pub mod identity;
+pub mod requests;
diff --git a/dal/writers/requests.rs b/dal/writers/requests.rs
new file mode 100644
index 00000000..c48b36a3
--- /dev/null
+++ b/dal/writers/requests.rs
@@ -0,0 +1,83 @@
+extern crate duniter_crypto;
+extern crate duniter_documents;
+extern crate duniter_wotb;
+extern crate serde;
+extern crate serde_json;
+extern crate sqlite;
+
+use self::duniter_crypto::keys::ed25519;
+use self::duniter_documents::blockchain::v10::documents::certification::CompactCertificationDocument;
+use self::duniter_documents::blockchain::v10::documents::identity::IdentityDocument;
+use self::duniter_documents::Blockstamp;
+use self::duniter_wotb::NodeId;
+use super::super::block::DALBlock;
+use super::super::identity::DALIdentity;
+use super::super::DuniterDB;
+
+#[derive(Debug)]
+/// Contain a pending write request for blockchain database
+pub enum DBWriteRequest {
+ /// Newcomer
+ CreateIdentity(NodeId, Blockstamp, u64, IdentityDocument),
+ /// Active
+ RenewalIdentity(ed25519::PublicKey, Blockstamp, u64),
+ /// Excluded
+ ExcludeIdentity(NodeId, Blockstamp, u64),
+ /// Revoked
+ RevokeIdentity(NodeId, Blockstamp, u64),
+ /// Certification
+ CreateCert(Blockstamp, u64, CompactCertificationDocument),
+ /// Certification expiry
+ CertExpiry(NodeId, NodeId, Blockstamp, u64),
+ /// Write block
+ WriteBlock(DALBlock),
+ /// Revert block
+ RevertBlock(DALBlock),
+}
+
+impl DBWriteRequest {
+ pub fn apply(&self, currency: &str, db: &DuniterDB) {
+ match *self {
+ DBWriteRequest::CreateIdentity(
+ ref wotb_id,
+ ref blockstamp,
+ ref median_time,
+ ref idty_doc,
+ ) => {
+ trace!("DBWriteRequest::CreateIdentity...");
+ let idty = DALIdentity::create_identity(db, idty_doc, blockstamp.clone());
+ super::identity::write(&idty, wotb_id, db, blockstamp.clone(), *median_time);
+ trace!("DBWriteRequest::CreateIdentity...finish.");
+ }
+ DBWriteRequest::RenewalIdentity(ref pubkey, ref blockstamp, ref median_time) => {
+ trace!("DBWriteRequest::RenewalIdentity...");
+ let mut idty = DALIdentity::get_identity(currency, db, pubkey)
+ .expect("Fatal error : impossible ton renewal an identidy that don't exist !");
+ idty.renewal_identity(db, pubkey, blockstamp, *median_time, false);
+ trace!("DBWriteRequest::RenewalIdentity...");
+ }
+ DBWriteRequest::ExcludeIdentity(ref wotb_id, ref blockstamp, ref _median_time) => {
+ DALIdentity::exclude_identity(db, *wotb_id, *blockstamp, false);
+ }
+ DBWriteRequest::RevokeIdentity(ref wotb_id, ref blockstamp, ref _median_time) => {
+ DALIdentity::revoke_identity(db, *wotb_id, blockstamp, false);
+ }
+ DBWriteRequest::CreateCert(ref blockstamp, ref median_time, ref compact_cert) => {
+ trace!("DBWriteRequest::CreateCert...");
+ super::certification::write_certification(
+ compact_cert,
+ db,
+ blockstamp.clone(),
+ *median_time,
+ );
+ trace!("DBWriteRequest::CreateCert...finish");
+ }
+ DBWriteRequest::WriteBlock(ref dal_block) => {
+ trace!("DBWriteRequest::WriteBlock...");
+ super::block::write(db, &dal_block.block, dal_block.fork, dal_block.isolate);
+ trace!("DBWriteRequest::WriteBlock...finish");
+ }
+ _ => {}
+ }
+ }
+}
diff --git a/documents/blockchain/v10/documents/block.rs b/documents/blockchain/v10/documents/block.rs
index 0305af99..1b51c468 100644
--- a/documents/blockchain/v10/documents/block.rs
+++ b/documents/blockchain/v10/documents/block.rs
@@ -24,7 +24,7 @@ use blockchain::v10::documents::identity::IdentityDocument;
use blockchain::v10::documents::membership::MembershipDocument;
use blockchain::v10::documents::revocation::RevocationDocument;
use blockchain::v10::documents::transaction::TransactionDocument;
-use blockchain::v10::documents::{TextDocument, V10Document};
+use blockchain::v10::documents::*;
use blockchain::{BlockchainProtocol, Document, IntoSpecializedDocument};
use {BlockHash, BlockId, Blockstamp, Hash};
@@ -130,11 +130,11 @@ pub struct BlockDocument {
/// Leavers
pub leavers: Vec<MembershipDocument>,
/// Revokeds
- pub revoked: Vec<RevocationDocument>,
+ pub revoked: Vec<TextDocumentFormat<RevocationDocument>>,
/// Excludeds
pub excluded: Vec<ed25519::PublicKey>,
/// Certifications
- pub certifications: Vec<CertificationDocument>,
+ pub certifications: Vec<TextDocumentFormat<CertificationDocument>>,
/// Transactions
pub transactions: Vec<TransactionDocument>,
/// Part to sign
@@ -146,9 +146,6 @@ impl BlockDocument {
pub fn compute_inner_hash(&mut self) {
let mut sha256 = Sha256::new();
let inner_text = self.generate_compact_inner_text();
- /*if self.number.0 == 46473 {
- println!("#46473 raw_format=\"{}\"", inner_text);
- }*/
sha256.input_str(&inner_text);
self.inner_hash = Some(Hash::from_hex(&sha256.result_str()).unwrap());
}
@@ -176,7 +173,8 @@ impl BlockDocument {
));
self.hash = Some(BlockHash(Hash::from_hex(&sha256.result_str()).unwrap()));
}
- fn generate_compact_inner_text(&self) -> String {
+ /// Generate compact inner text (for compute inner_hash)
+ pub fn generate_compact_inner_text(&self) -> String {
let mut identities_str = String::from("");
for identity in self.identities.clone() {
identities_str.push_str("\n");
@@ -205,7 +203,7 @@ impl BlockDocument {
let mut revokeds_str = String::from("");
for revocation in self.revoked.clone() {
revokeds_str.push_str("\n");
- revokeds_str.push_str(&revocation.generate_compact_text());
+ revokeds_str.push_str(&revocation.as_compact_text());
}
let mut excludeds_str = String::from("");
for exclusion in self.excluded.clone() {
@@ -215,7 +213,7 @@ impl BlockDocument {
let mut certifications_str = String::from("");
for certification in self.certifications.clone() {
certifications_str.push_str("\n");
- certifications_str.push_str(&certification.generate_compact_text());
+ certifications_str.push_str(&certification.as_compact_text());
}
let mut transactions_str = String::from("");
for transaction in self.transactions.clone() {
@@ -313,12 +311,8 @@ impl Document for BlockDocument {
}
}
-impl TextDocument for BlockDocument {
- fn as_text(&self) -> &str {
- panic!();
- }
-
- fn generate_compact_text(&self) -> String {
+impl CompactTextDocument for BlockDocument {
+ fn as_compact_text(&self) -> String {
let compact_inner_text = self.generate_compact_inner_text();
format!(
"{}InnerHash: {}\nNonce: ",
@@ -328,6 +322,18 @@ impl TextDocument for BlockDocument {
}
}
+impl TextDocument for BlockDocument {
+ type CompactTextDocument_ = BlockDocument;
+
+ fn as_text(&self) -> &str {
+ panic!();
+ }
+
+ fn to_compact_document(&self) -> Self::CompactTextDocument_ {
+ self.clone()
+ }
+}
+
impl IntoSpecializedDocument<BlockchainProtocol> for BlockDocument {
fn into_specialized(self) -> BlockchainProtocol {
BlockchainProtocol::V10(Box::new(V10Document::Block(Box::new(self))))
@@ -506,7 +512,7 @@ a9PHPuSfw7jW8FRQHXFsGi/bnLjbtDnTYvEVgUC9u0WlR7GVofa+Xb+l5iy6NwuEXiwvueAkf08wPVY8
leavers: Vec::new(),
revoked: Vec::new(),
excluded: Vec::new(),
- certifications: vec![cert1],
+ certifications: vec![TextDocumentFormat::Complete(cert1)],
transactions: vec![tx1, tx2],
inner_hash_and_nonce_str: String::new(),
};
diff --git a/documents/blockchain/v10/documents/certification.rs b/documents/blockchain/v10/documents/certification.rs
index b3e8857c..84259183 100644
--- a/documents/blockchain/v10/documents/certification.rs
+++ b/documents/blockchain/v10/documents/certification.rs
@@ -21,11 +21,9 @@ use self::serde::ser::{Serialize, Serializer};
use duniter_crypto::keys::{ed25519, PublicKey, Signature};
use regex::Regex;
-use blockchain::v10::documents::{
- StandardTextDocumentParser, TextDocument, TextDocumentBuilder, V10Document,
- V10DocumentParsingError,
-};
+use blockchain::v10::documents::*;
use blockchain::{BlockchainProtocol, Document, DocumentBuilder, IntoSpecializedDocument};
+use BlockId;
use Blockstamp;
lazy_static! {
@@ -34,6 +32,31 @@ lazy_static! {
).unwrap();
}
+#[derive(Debug, Copy, Clone)]
+/// Wrap an Compact Revocation document (in block content)
+pub struct CompactCertificationDocument {
+ /// Issuer
+ pub issuer: ed25519::PublicKey,
+ /// Target
+ pub target: ed25519::PublicKey,
+ /// Blockstamp
+ pub block_number: BlockId,
+ /// Signature
+ pub signature: ed25519::Signature,
+}
+
+impl CompactTextDocument for CompactCertificationDocument {
+ fn as_compact_text(&self) -> String {
+ format!(
+ "{issuer}:{target}:{block_number}:{signature}",
+ issuer = self.issuer,
+ target = self.target,
+ block_number = self.block_number.0,
+ signature = self.signature,
+ )
+ }
+}
+
/// Wrap an Certification document.
///
/// Must be created by parsing a text document or using a builder.
@@ -109,27 +132,28 @@ impl Document for CertificationDocument {
}
impl TextDocument for CertificationDocument {
+ type CompactTextDocument_ = CompactCertificationDocument;
+
fn as_text(&self) -> &str {
&self.text
}
- fn generate_compact_text(&self) -> String {
- format!(
- "{issuer}:{target}:{block_number}:{signature}",
- issuer = self.issuers[0],
- target = self.target,
- block_number = self.blockstamp.id.0,
- signature = self.signatures[0],
- )
+ fn to_compact_document(&self) -> Self::CompactTextDocument_ {
+ CompactCertificationDocument {
+ issuer: self.issuers[0],
+ target: self.target,
+ block_number: self.blockstamp().id,
+ signature: self.signatures()[0],
+ }
}
}
-impl Serialize for CertificationDocument {
+impl Serialize for TextDocumentFormat<CertificationDocument> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
- serializer.serialize_str(&self.generate_compact_text())
+ serializer.serialize_str(&self.as_compact_text())
}
}
diff --git a/documents/blockchain/v10/documents/identity.rs b/documents/blockchain/v10/documents/identity.rs
index 6e986565..40bd02bb 100644
--- a/documents/blockchain/v10/documents/identity.rs
+++ b/documents/blockchain/v10/documents/identity.rs
@@ -21,10 +21,7 @@ use self::serde::ser::{Serialize, Serializer};
use duniter_crypto::keys::{ed25519, PublicKey};
use regex::Regex;
-use blockchain::v10::documents::{
- StandardTextDocumentParser, TextDocument, TextDocumentBuilder, V10Document,
- V10DocumentParsingError,
-};
+use blockchain::v10::documents::*;
use blockchain::{BlockchainProtocol, Document, DocumentBuilder, IntoSpecializedDocument};
use Blockstamp;
@@ -93,12 +90,8 @@ impl Document for IdentityDocument {
}
}
-impl TextDocument for IdentityDocument {
- fn as_text(&self) -> &str {
- &self.text
- }
-
- fn generate_compact_text(&self) -> String {
+impl CompactTextDocument for IdentityDocument {
+ fn as_compact_text(&self) -> String {
format!(
"{issuer}:{signature}:{blockstamp}:{username}",
issuer = self.issuers[0],
@@ -109,6 +102,18 @@ impl TextDocument for IdentityDocument {
}
}
+impl TextDocument for IdentityDocument {
+ type CompactTextDocument_ = IdentityDocument;
+
+ fn as_text(&self) -> &str {
+ &self.text
+ }
+
+ fn to_compact_document(&self) -> Self::CompactTextDocument_ {
+ self.clone()
+ }
+}
+
impl Serialize for IdentityDocument {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
diff --git a/documents/blockchain/v10/documents/membership.rs b/documents/blockchain/v10/documents/membership.rs
index 0cc53d51..2e313601 100644
--- a/documents/blockchain/v10/documents/membership.rs
+++ b/documents/blockchain/v10/documents/membership.rs
@@ -21,10 +21,7 @@ use self::serde::ser::{Serialize, Serializer};
use duniter_crypto::keys::{ed25519, PublicKey};
use regex::Regex;
-use blockchain::v10::documents::{
- StandardTextDocumentParser, TextDocument, TextDocumentBuilder, V10Document,
- V10DocumentParsingError,
-};
+use blockchain::v10::documents::*;
use blockchain::{BlockchainProtocol, Document, DocumentBuilder, IntoSpecializedDocument};
use Blockstamp;
@@ -114,12 +111,8 @@ impl Document for MembershipDocument {
}
}
-impl TextDocument for MembershipDocument {
- fn as_text(&self) -> &str {
- &self.text
- }
-
- fn generate_compact_text(&self) -> String {
+impl CompactTextDocument for MembershipDocument {
+ fn as_compact_text(&self) -> String {
format!(
"{issuer}:{signature}:{blockstamp}:{idty_blockstamp}:{username}",
issuer = self.issuers[0],
@@ -131,6 +124,18 @@ impl TextDocument for MembershipDocument {
}
}
+impl TextDocument for MembershipDocument {
+ type CompactTextDocument_ = MembershipDocument;
+
+ fn as_text(&self) -> &str {
+ &self.text
+ }
+
+ fn to_compact_document(&self) -> Self::CompactTextDocument_ {
+ self.clone()
+ }
+}
+
impl Serialize for MembershipDocument {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
diff --git a/documents/blockchain/v10/documents/mod.rs b/documents/blockchain/v10/documents/mod.rs
index 3557543a..495190dd 100644
--- a/documents/blockchain/v10/documents/mod.rs
+++ b/documents/blockchain/v10/documents/mod.rs
@@ -42,6 +42,8 @@ pub use blockchain::v10::documents::transaction::{
TransactionDocument, TransactionDocumentBuilder, TransactionDocumentParser,
};
+use std::marker::Sized;
+
// Use of lazy_static so the regex is only compiled at first use.
lazy_static! {
static ref DOCUMENT_REGEX: Regex = Regex::new(
@@ -54,6 +56,25 @@ lazy_static! {
static ref SIGNATURES_REGEX: Regex = Regex::new("[[:alnum:]+/=]+\n?").unwrap();
}
+#[derive(Debug, Clone)]
+/// Contains a document in full or compact format
+pub enum TextDocumentFormat<D: TextDocument> {
+ /// Complete format (Allows to check the validity of the signature)
+ Complete(D),
+ /// Format present in the blocks (does not always allow to verify the signature)
+ Compact(D::CompactTextDocument_),
+}
+
+impl<D: TextDocument> TextDocumentFormat<D> {
+ /// To compact document
+ pub fn to_compact_document(&self) -> D::CompactTextDocument_ {
+ match *self {
+ TextDocumentFormat::Complete(ref doc) => doc.to_compact_document(),
+ TextDocumentFormat::Compact(ref compact_doc) => (*compact_doc).clone(),
+ }
+ }
+}
+
/// List of wrapped document types.
///
/// > TODO Add wrapped types in enum variants.
@@ -78,8 +99,30 @@ pub enum V10Document {
Revocation(Box<RevocationDocument>),
}
+/// Trait for a compact V10 document.
+pub trait CompactTextDocument: Sized + Clone {
+ /// Generate document compact text.
+ /// the compact format is the one used in the blocks.
+ ///
+ /// - Don't contains leading signatures
+ /// - Contains line breaks on all line.
+ fn as_compact_text(&self) -> String;
+}
+
+impl<D: TextDocument> CompactTextDocument for TextDocumentFormat<D> {
+ fn as_compact_text(&self) -> String {
+ match *self {
+ TextDocumentFormat::Complete(ref doc) => doc.generate_compact_text(),
+ TextDocumentFormat::Compact(ref doc) => doc.as_compact_text(),
+ }
+ }
+}
+
/// Trait for a V10 document.
pub trait TextDocument: Document<PublicKey = ed25519::PublicKey, CurrencyType = str> {
+ /// Type of associated compact document.
+ type CompactTextDocument_: CompactTextDocument;
+
/// Return document as text.
fn as_text(&self) -> &str;
@@ -100,12 +143,19 @@ pub trait TextDocument: Document<PublicKey = ed25519::PublicKey, CurrencyType =
text
}
+ /// Generate compact document.
+ /// the compact format is the one used in the blocks.
+ /// - Don't contains leading signatures
+ fn to_compact_document(&self) -> Self::CompactTextDocument_;
+
/// Generate document compact text.
/// the compact format is the one used in the blocks.
///
/// - Don't contains leading signatures
/// - Contains line breaks on all line.
- fn generate_compact_text(&self) -> String;
+ fn generate_compact_text(&self) -> String {
+ self.to_compact_document().as_compact_text()
+ }
}
/// Trait for a V10 document builder.
diff --git a/documents/blockchain/v10/documents/revocation.rs b/documents/blockchain/v10/documents/revocation.rs
index b954ae13..d40d9704 100644
--- a/documents/blockchain/v10/documents/revocation.rs
+++ b/documents/blockchain/v10/documents/revocation.rs
@@ -21,10 +21,7 @@ use self::serde::ser::{Serialize, Serializer};
use duniter_crypto::keys::{ed25519, PublicKey, Signature};
use regex::Regex;
-use blockchain::v10::documents::{
- StandardTextDocumentParser, TextDocument, TextDocumentBuilder, V10Document,
- V10DocumentParsingError,
-};
+use blockchain::v10::documents::*;
use blockchain::{BlockchainProtocol, Document, DocumentBuilder, IntoSpecializedDocument};
use Blockstamp;
@@ -37,6 +34,25 @@ lazy_static! {
).unwrap();
}
+#[derive(Debug, Copy, Clone)]
+/// Wrap an Compact Revocation document (in block content)
+pub struct CompactRevocationDocument {
+ /// Issuer
+ pub issuer: ed25519::PublicKey,
+ /// Signature
+ pub signature: ed25519::Signature,
+}
+
+impl CompactTextDocument for CompactRevocationDocument {
+ fn as_compact_text(&self) -> String {
+ format!(
+ "{issuer}:{signature}",
+ issuer = self.issuer,
+ signature = self.signature,
+ )
+ }
+}
+
/// Wrap an Revocation document.
///
/// Must be created by parsing a text document or using a builder.
@@ -98,25 +114,26 @@ impl Document for RevocationDocument {
}
impl TextDocument for RevocationDocument {
+ type CompactTextDocument_ = CompactRevocationDocument;
+
fn as_text(&self) -> &str {
&self.text
}
- fn generate_compact_text(&self) -> String {
- format!(
- "{issuer}:{signature}",
- issuer = self.issuers[0],
- signature = self.signatures[0],
- )
+ fn to_compact_document(&self) -> Self::CompactTextDocument_ {
+ CompactRevocationDocument {
+ issuer: self.issuers[0],
+ signature: self.signatures[0],
+ }
}
}
-impl Serialize for RevocationDocument {
+impl Serialize for TextDocumentFormat<RevocationDocument> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
- serializer.serialize_str(&self.generate_compact_text())
+ serializer.serialize_str(&self.as_compact_text())
}
}
diff --git a/documents/blockchain/v10/documents/transaction.rs b/documents/blockchain/v10/documents/transaction.rs
index efcf04a7..992640c8 100644
--- a/documents/blockchain/v10/documents/transaction.rs
+++ b/documents/blockchain/v10/documents/transaction.rs
@@ -25,10 +25,7 @@ use regex::RegexBuilder;
use self::serde::ser::{Serialize, Serializer};
-use blockchain::v10::documents::{
- StandardTextDocumentParser, TextDocument, TextDocumentBuilder, V10Document,
- V10DocumentParsingError,
-};
+use blockchain::v10::documents::*;
use blockchain::{BlockchainProtocol, Document, DocumentBuilder, IntoSpecializedDocument};
use Blockstamp;
@@ -442,12 +439,8 @@ impl Document for TransactionDocument {
}
}
-impl TextDocument for TransactionDocument {
- fn as_text(&self) -> &str {
- &self.text
- }
-
- fn generate_compact_text(&self) -> String {
+impl CompactTextDocument for TransactionDocument {
+ fn as_compact_text(&self) -> String {
let mut issuers_str = String::from("");
for issuer in self.issuers.clone() {
issuers_str.push_str("\n");
@@ -499,12 +492,24 @@ impl TextDocument for TransactionDocument {
}
}
+impl TextDocument for TransactionDocument {
+ type CompactTextDocument_ = TransactionDocument;
+
+ fn as_text(&self) -> &str {
+ &self.text
+ }
+
+ fn to_compact_document(&self) -> Self::CompactTextDocument_ {
+ self.clone()
+ }
+}
+
impl Serialize for TransactionDocument {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
- let compact_text = self.generate_compact_text();
+ let compact_text = self.to_compact_document().generate_compact_text();
serializer.serialize_str(&compact_text.replace("\n", "$"))
}
}
diff --git a/network/lib.rs b/network/lib.rs
index d02928b9..d6b42720 100644
--- a/network/lib.rs
+++ b/network/lib.rs
@@ -109,12 +109,6 @@ pub trait NetworkConf: Debug + Copy + Clone + PartialEq {}
pub struct NetworkBlockV10 {
/// Uncompleted block document
pub uncompleted_block_doc: BlockDocument,
- /// Joiners
- pub joiners: Vec<serde_json::Value>,
- /// actives
- pub actives: Vec<serde_json::Value>,
- /// leavers
- pub leavers: Vec<serde_json::Value>,
/// revoked
pub revoked: Vec<serde_json::Value>,
/// certifications
diff --git a/ws2p/lib.rs b/ws2p/lib.rs
index aef80ddd..835e3c0d 100644
--- a/ws2p/lib.rs
+++ b/ws2p/lib.rs
@@ -1063,22 +1063,28 @@ impl WS2PModuleDatas {
pub fn connect_to_know_endpoints(&mut self) -> () {
let mut count_established_connections = 0;
let mut reachable_endpoints = Vec::new();
+ let mut unreachable_endpoints = Vec::new();
for (_ws2p_full_id, (ep, state)) in self.ws2p_endpoints.clone() {
match state {
WS2PConnectionState::Established => count_established_connections += 1,
WS2PConnectionState::NeverTry
| WS2PConnectionState::Close
| WS2PConnectionState::Denial => reachable_endpoints.push(ep),
- _ => {}
+ _ => unreachable_endpoints.push(ep),
}
}
let mut free_outcoming_rooms =
self.conf.clone().unwrap().outcoming_quota - count_established_connections;
- for ep in reachable_endpoints {
- if free_outcoming_rooms > 0 {
- free_outcoming_rooms -= 1;
- self.connect_to_without_checking_quotas(ep);
- }
+ while free_outcoming_rooms > 0 {
+ let ep = if !reachable_endpoints.is_empty() {
+ reachable_endpoints.pop().unwrap()
+ } else if !unreachable_endpoints.is_empty() {
+ unreachable_endpoints.pop().unwrap()
+ } else {
+ break;
+ };
+ self.connect_to_without_checking_quotas(ep);
+ free_outcoming_rooms -= 1;
}
}
pub fn connect_to(&mut self, endpoint: NetworkEndpoint) -> () {
--
GitLab