diff --git a/Cargo.lock b/Cargo.lock
index b727cd5f2799ffd74bc980811a3f4fac2c8489dc..edac3fe38ec4e0ab9d8f8442236f46daac2b29cb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -810,6 +810,7 @@ dependencies = [
 name = "dubp-user-docs-tests-tools"
 version = "0.1.0"
 dependencies = [
+ "dubp-block-doc 0.1.0",
  "dubp-common-doc 0.1.0",
  "dubp-currency-params 0.2.0",
  "dubp-user-docs 0.14.0",
@@ -941,6 +942,7 @@ dependencies = [
  "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "json-pest-parser 0.2.0",
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "pbr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/lib/modules/blockchain/blockchain/Cargo.toml b/lib/modules/blockchain/blockchain/Cargo.toml
index dd0a21d593afe7f195b462afeac4a742a41e7b48..bf03e517a8cac3cf1beee1e7eaa42eb3b64ece75 100644
--- a/lib/modules/blockchain/blockchain/Cargo.toml
+++ b/lib/modules/blockchain/blockchain/Cargo.toml
@@ -42,5 +42,6 @@ dup-crypto-tests-tools = { path = "../../../tests-tools/crypto-tests-tools" }
 dubp-user-docs-tests-tools = { path = "../../../tests-tools/user-docs-tests-tools" }
 dubp-blocks-tests-tools = { path = "../../../tests-tools/blocks-tests-tools" }
 durs-common-tests-tools = { path = "../../../tests-tools/common-tests-tools" }
+maplit = "1.0.1"
 pretty_assertions = "0.5.1"
 tempfile = "3.1.0"
diff --git a/lib/modules/blockchain/blockchain/src/dubp/mod.rs b/lib/modules/blockchain/blockchain/src/dubp.rs
similarity index 78%
rename from lib/modules/blockchain/blockchain/src/dubp/mod.rs
rename to lib/modules/blockchain/blockchain/src/dubp.rs
index 9066028a0905d7f09c91535fa85e4363c0f0327c..cd964bd215f94ec6190f82c8860ac99931e492f8 100644
--- a/lib/modules/blockchain/blockchain/src/dubp/mod.rs
+++ b/lib/modules/blockchain/blockchain/src/dubp.rs
@@ -18,14 +18,18 @@
 pub mod apply;
 pub mod check;
 
-use crate::*;
-use apply::*;
-use check::*;
-use dubp_block_doc::block::{BlockDocumentTrait, VerifyBlockHashError};
+use crate::dubp::apply::{apply_valid_block, ApplyValidBlockError, ValidBlockApplyReqs};
+use crate::dubp::check::global::verify_global_validity_block;
+use crate::dubp::check::local::verify_local_validity_block;
+use crate::dubp::check::InvalidBlockError;
+use crate::BlockchainModule;
+use dubp_block_doc::block::BlockDocumentTrait;
+use dubp_block_doc::BlockDocument;
 use dubp_common_doc::traits::Document;
 use dubp_common_doc::{BlockNumber, Blockstamp};
 use durs_bc_db_reader::blocks::DbBlock;
-use durs_bc_db_writer::*;
+use durs_bc_db_reader::DbError;
+use durs_bc_db_writer::{Db, DbWriter};
 use unwrap::unwrap;
 
 #[derive(Debug, Clone)]
@@ -38,16 +42,15 @@ pub enum CheckAndApplyBlockReturn {
 #[derive(Debug)]
 pub enum BlockError {
     AlreadyHaveBlock,
+    ApplyValidBlockError(ApplyValidBlockError),
     BlockOrOutForkWindow,
-    VerifyBlockHashError(VerifyBlockHashError),
     DbError(DbError),
     InvalidBlock(InvalidBlockError),
-    ApplyValidBlockError(ApplyValidBlockError),
 }
 
-impl From<VerifyBlockHashError> for BlockError {
-    fn from(err: VerifyBlockHashError) -> Self {
-        BlockError::VerifyBlockHashError(err)
+impl From<ApplyValidBlockError> for BlockError {
+    fn from(e: ApplyValidBlockError) -> Self {
+        Self::ApplyValidBlockError(e)
     }
 }
 
@@ -57,9 +60,9 @@ impl From<DbError> for BlockError {
     }
 }
 
-impl From<ApplyValidBlockError> for BlockError {
-    fn from(err: ApplyValidBlockError) -> Self {
-        BlockError::ApplyValidBlockError(err)
+impl From<InvalidBlockError> for BlockError {
+    fn from(e: InvalidBlockError) -> Self {
+        Self::InvalidBlock(e)
     }
 }
 
@@ -76,8 +79,15 @@ pub fn check_and_apply_block(
         block_doc.previous_hash(),
     )?;
 
+    // Verify proof of work
+    // The case where the block has none hash is captured by verify_block_hashs below
+    if let Some(hash) = block_doc.hash() {
+        self::check::pow::verify_hash_pattern(hash.0, block_doc.pow_min())
+            .map_err(InvalidBlockError::Pow)?;
+    }
+
     // Verify block hashs
-    dubp::check::hashs::verify_block_hashs(&block_doc)?;
+    crate::dubp::check::hashs::verify_block_hashs(&block_doc).map_err(InvalidBlockError::Hashs)?;
 
     // Check block chainability
     if (block_doc.number().0 == 0 && bc.current_blockstamp == Blockstamp::default())
@@ -89,19 +99,25 @@ pub fn check_and_apply_block(
             "check_and_apply_block: block {} chainable!",
             block_doc.blockstamp()
         );
+
+        // Local verification
+        verify_local_validity_block(&block_doc, bc.currency_params)
+            .map_err(InvalidBlockError::Local)?;
+
         // Detect expire_certs
         let blocks_expiring = Vec::with_capacity(0);
         let expire_certs =
             durs_bc_db_reader::indexes::certs::find_expire_certs(db, w.as_ref(), blocks_expiring)?;
 
         // Verify block validity (check all protocol rule, very long !)
-        verify_block_validity(
+        verify_global_validity_block(
             &block_doc,
             db,
             w.as_ref(),
             &bc.wot_index,
             &bc.wot_databases.wot_db,
-        )?;
+        )
+        .map_err(InvalidBlockError::Global)?;
 
         // If we're in block genesis, get the currency parameters
         if block_doc.number() == BlockNumber(0) {
diff --git a/lib/modules/blockchain/blockchain/src/dubp/check.rs b/lib/modules/blockchain/blockchain/src/dubp/check.rs
new file mode 100644
index 0000000000000000000000000000000000000000..10b0ff01bc3da03e29a4963157840abb43005980
--- /dev/null
+++ b/lib/modules/blockchain/blockchain/src/dubp/check.rs
@@ -0,0 +1,29 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// 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/>.
+
+//! Sub-module checking if a block complies with all the rules of the (DUBP DUniter Blockchain Protocol).
+
+pub mod global;
+pub mod hashs;
+pub mod local;
+pub mod pow;
+
+#[derive(Debug)]
+pub enum InvalidBlockError {
+    Global(global::GlobalVerifyBlockError),
+    Hashs(dubp_block_doc::block::VerifyBlockHashError),
+    Local(local::LocalVerifyBlockError),
+    Pow(pow::BlockPoWError),
+}
diff --git a/lib/modules/blockchain/blockchain/src/dubp/check/mod.rs b/lib/modules/blockchain/blockchain/src/dubp/check/global.rs
similarity index 72%
rename from lib/modules/blockchain/blockchain/src/dubp/check/mod.rs
rename to lib/modules/blockchain/blockchain/src/dubp/check/global.rs
index be5d5a91624de86d9de898795b4658492af70ca8..483c2ece4f78dc945fd678789b2c15db3b9b2bec 100644
--- a/lib/modules/blockchain/blockchain/src/dubp/check/mod.rs
+++ b/lib/modules/blockchain/blockchain/src/dubp/check/global.rs
@@ -15,31 +15,36 @@
 
 //! Sub-module checking if a block complies with all the rules of the (DUBP DUniter Blockchain Protocol).
 
-pub mod hashs;
-
-use crate::dubp::BlockError;
 use dubp_block_doc::block::{BlockDocument, BlockDocumentTrait};
 use dubp_common_doc::traits::Document;
 use dubp_common_doc::BlockNumber;
 use dup_crypto::keys::PubKey;
-use durs_bc_db_reader::DbReader;
-use durs_bc_db_writer::*;
+use durs_bc_db_reader::{DbError, DbReadable, DbReader};
+use durs_bc_db_writer::BinFreeStructDb;
+use durs_common_tools::traits::bool_ext::BoolExt;
 use durs_wot::*;
 use std::collections::HashMap;
 
-#[derive(Debug, Copy, Clone)]
-pub enum InvalidBlockError {
+#[derive(Debug)]
+pub enum GlobalVerifyBlockError {
+    DbError(DbError),
     NoPreviousBlock,
     VersionDecrease,
 }
 
-pub fn verify_block_validity<DB, R, W>(
+impl From<DbError> for GlobalVerifyBlockError {
+    fn from(err: DbError) -> Self {
+        GlobalVerifyBlockError::DbError(err)
+    }
+}
+
+pub fn verify_global_validity_block<DB, R, W>(
     block: &BlockDocument,
     db: &DB,
     r: &R,
     _wot_index: &HashMap<PubKey, WotId>,
     _wot_db: &BinFreeStructDb<W>,
-) -> Result<(), BlockError>
+) -> Result<(), GlobalVerifyBlockError>
 where
     DB: DbReadable,
     R: DbReader,
@@ -55,15 +60,14 @@ where
         )?;
 
         // Previous block must exist
-        if previous_block_opt.is_none() {
-            return Err(BlockError::InvalidBlock(InvalidBlockError::NoPreviousBlock));
-        }
+        previous_block_opt
+            .is_some()
+            .or_err(GlobalVerifyBlockError::NoPreviousBlock)?;
         let previous_block = previous_block_opt.expect("safe unwrap");
 
         // Block version must not decrease
-        if previous_block.version() > block.version() {
-            return Err(BlockError::InvalidBlock(InvalidBlockError::VersionDecrease));
-        }
+        (block.version() >= previous_block.version())
+            .or_err(GlobalVerifyBlockError::VersionDecrease)?;
     }
 
     Ok(())
diff --git a/lib/modules/blockchain/blockchain/src/dubp/check/local.rs b/lib/modules/blockchain/blockchain/src/dubp/check/local.rs
new file mode 100644
index 0000000000000000000000000000000000000000..3178bb2641f6d8608f60bf9168a15518f67a78c5
--- /dev/null
+++ b/lib/modules/blockchain/blockchain/src/dubp/check/local.rs
@@ -0,0 +1,209 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// 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/>.
+
+//! Sub-module checking if the content of a block is consistent.
+
+pub mod genesis;
+pub mod not_genesis;
+pub mod tx_doc;
+
+use self::genesis::LocalVerifyGenesisBlockError;
+use self::not_genesis::LocalVerifyNotGenesisBlockError;
+use self::tx_doc::TransactionDocumentError;
+
+use dubp_block_doc::block::v10::BlockDocumentV10;
+use dubp_block_doc::{block::BlockDocumentTrait, BlockDocument};
+use dubp_common_doc::errors::DocumentSigsErr;
+use dubp_common_doc::traits::Document;
+use dubp_common_doc::BlockNumber;
+use dubp_currency_params::CurrencyParameters;
+use durs_common_tools::fatal_error;
+
+#[derive(Debug, PartialEq)]
+/// Local verification of a block error
+pub enum LocalVerifyBlockError {
+    /// Wrong block version
+    Version {
+        expected_version: Vec<usize>,
+        actual_version: u32,
+    },
+    /// Genesis block specific rules
+    LocalVerifyGenesisBlockError(LocalVerifyGenesisBlockError),
+    /// Not-genesis block specific rules
+    LocalVerifyNotGenesisBlockError(LocalVerifyNotGenesisBlockError),
+    /// Signature error
+    BlockSignatureError(DocumentSigsErr),
+    /// Identity signature error
+    IdentitySignatureError(DocumentSigsErr),
+    /// Joiner signature error
+    JoinerSignatureError(DocumentSigsErr),
+    /// Active signature error
+    ActiveSignatureError(DocumentSigsErr),
+    /// Leaver signature error
+    LeaverSignatureError(DocumentSigsErr),
+    /// Missing issuer
+    MissingIssuer,
+    /// Too many issuers (> 1)
+    TooManyIssuers,
+    /// Transaction Document Error
+    TransactionDocumentError(TransactionDocumentError),
+}
+
+impl From<LocalVerifyGenesisBlockError> for LocalVerifyBlockError {
+    fn from(err: LocalVerifyGenesisBlockError) -> Self {
+        Self::LocalVerifyGenesisBlockError(err)
+    }
+}
+
+impl From<LocalVerifyNotGenesisBlockError> for LocalVerifyBlockError {
+    fn from(err: LocalVerifyNotGenesisBlockError) -> Self {
+        Self::LocalVerifyNotGenesisBlockError(err)
+    }
+}
+
+impl From<TransactionDocumentError> for LocalVerifyBlockError {
+    fn from(err: TransactionDocumentError) -> Self {
+        Self::TransactionDocumentError(err)
+    }
+}
+
+/// Local verification of a block document according to rules of RFC0009
+pub fn verify_local_validity_block(
+    block: &BlockDocument,
+    currency_parameters_opt: Option<CurrencyParameters>,
+) -> Result<(), LocalVerifyBlockError> {
+    if block.number() == BlockNumber(0) {
+        // Check the local rules specific to genesis blocks
+        self::genesis::local_validation_genesis_block(block)?;
+    } else if let Some(currency_parameters) = currency_parameters_opt {
+        // Check the local rules specific to non-genesis blocks
+        self::not_genesis::local_validation_not_genesis_block(block, currency_parameters)?;
+    } else {
+        fatal_error!("We must have currency parameters when we check a non-genesis block.");
+    }
+
+    match block {
+        BlockDocument::V10(block) => verify_local_validity_block_v10(block),
+    }
+}
+
+/// Local verification of a block document V10 according to rules of RFC0009
+pub fn verify_local_validity_block_v10(
+    block: &BlockDocumentV10,
+) -> Result<(), LocalVerifyBlockError> {
+    // Version
+    if !(block.version == 10 || block.version == 11) {
+        return Err(LocalVerifyBlockError::Version {
+            expected_version: vec![10, 11],
+            actual_version: block.version,
+        });
+    }
+
+    // Issuers
+    if block.issuers.is_empty() {
+        return Err(LocalVerifyBlockError::MissingIssuer);
+    } else if block.issuers.len() > 1 {
+        return Err(LocalVerifyBlockError::TooManyIssuers);
+    }
+
+    // Check signatures of block and wot events
+    // As it has been checked that block.issuers.len() == 1 and as
+    // block.issuers.len() == block.signatures.len() is check in block.verify_signatures()
+    // there is no need to check that block.signatures.len() == 1
+    block
+        .verify_signatures()
+        .map_err(LocalVerifyBlockError::BlockSignatureError)?;
+    for identity in &block.identities {
+        identity
+            .verify_signatures()
+            .map_err(LocalVerifyBlockError::IdentitySignatureError)?;
+    }
+    for joiner in &block.joiners {
+        joiner
+            .verify_signatures()
+            .map_err(LocalVerifyBlockError::JoinerSignatureError)?;
+    }
+    for active in &block.actives {
+        active
+            .verify_signatures()
+            .map_err(LocalVerifyBlockError::ActiveSignatureError)?;
+    }
+    for leaver in &block.leavers {
+        leaver
+            .verify_signatures()
+            .map_err(LocalVerifyBlockError::LeaverSignatureError)?;
+    }
+
+    // Check transactions
+    for tx in &block.transactions {
+        self::tx_doc::local_verify_tx_doc(tx)?;
+    }
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+
+    use super::*;
+    use dubp_block_doc::BlockDocument;
+    use dubp_blocks_tests_tools::mocks::block_params::gen_mock_currency_parameters;
+    use dubp_blocks_tests_tools::mocks::gen_mock_normal_block_v10;
+
+    #[test]
+    fn test_verify_not_genesis_block_valid() {
+        let currency_params = gen_mock_currency_parameters();
+        let block = gen_mock_normal_block_v10();
+        assert!(
+            verify_local_validity_block(&BlockDocument::V10(block), Some(currency_params)).is_ok()
+        );
+    }
+
+    #[test]
+    fn test_verify_not_genesis_block_wrong_version() {
+        let currency_params = gen_mock_currency_parameters();
+        let mut block = gen_mock_normal_block_v10();
+        block.version = 14;
+
+        let expected = Err(LocalVerifyBlockError::Version {
+            expected_version: vec![10, 11],
+            actual_version: 14,
+        });
+        let actual = verify_local_validity_block(&BlockDocument::V10(block), Some(currency_params));
+        assert_eq!(expected, actual);
+    }
+
+    #[test]
+    fn test_verify_not_genesis_block_issuers_empty() {
+        let currency_params = gen_mock_currency_parameters();
+        let mut block = gen_mock_normal_block_v10();
+        block.issuers.clear();
+
+        let expected = Err(LocalVerifyBlockError::MissingIssuer);
+        let actual = verify_local_validity_block(&BlockDocument::V10(block), Some(currency_params));
+        assert_eq!(expected, actual);
+    }
+
+    #[test]
+    fn test_verify_not_genesis_block_none_too_many_issuers() {
+        let currency_params = gen_mock_currency_parameters();
+        let mut block = gen_mock_normal_block_v10();
+        block.issuers.push(block.issuers[0]);
+
+        let expected = Err(LocalVerifyBlockError::TooManyIssuers);
+        let actual = verify_local_validity_block(&BlockDocument::V10(block), Some(currency_params));
+        assert_eq!(expected, actual);
+    }
+}
diff --git a/lib/modules/blockchain/blockchain/src/dubp/check/local/genesis.rs b/lib/modules/blockchain/blockchain/src/dubp/check/local/genesis.rs
new file mode 100644
index 0000000000000000000000000000000000000000..5099de4ab854c2c985b00395a71fb66a8c2632ce
--- /dev/null
+++ b/lib/modules/blockchain/blockchain/src/dubp/check/local/genesis.rs
@@ -0,0 +1,194 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// 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/>.
+
+//! Verifies if a genesis block verifies the local rules specific to genesis blocks
+
+use dubp_block_doc::block::v10::BlockDocumentV10;
+use dubp_block_doc::BlockDocument;
+use dubp_common_doc::BlockNumber;
+use durs_common_tools::traits::bool_ext::BoolExt;
+
+/// Local verification of errors specific to a Genesis Block
+#[derive(Debug, PartialEq)]
+pub enum LocalVerifyGenesisBlockError {
+    /// Block number is not zero
+    NonZeroBlockNumber { block_number: BlockNumber },
+    /// A dividend is provided
+    UnexpectedDividend,
+    /// A previous hash is provided
+    UnexpectedPreviousHash,
+    /// A previous issuer is provided
+    UnexpectedPreviousIssuer,
+    /// No paramters are provided
+    MissingParameters,
+    /// Unit base is not zero
+    NonZeroUnitBase { unit_base: usize },
+    /// The block time is different from the median time
+    TimeError { block_time: u64, median_time: u64 },
+}
+
+/// Verifies local rules specific to a genesis block
+pub fn local_validation_genesis_block(
+    block: &BlockDocument,
+) -> Result<(), LocalVerifyGenesisBlockError> {
+    match block {
+        BlockDocument::V10(block) => local_validation_genesis_block_v10(block),
+    }
+}
+
+fn local_validation_genesis_block_v10(
+    block: &BlockDocumentV10,
+) -> Result<(), LocalVerifyGenesisBlockError> {
+    // block_number must be equal to zero
+    (block.number == BlockNumber(0)).or_err(LocalVerifyGenesisBlockError::NonZeroBlockNumber {
+        block_number: block.number,
+    })?;
+
+    // Dividend must be none
+    block
+        .dividend
+        .is_none()
+        .or_err(LocalVerifyGenesisBlockError::UnexpectedDividend)?;
+
+    // Previous Hash must be none
+    block
+        .previous_hash
+        .is_none()
+        .or_err(LocalVerifyGenesisBlockError::UnexpectedPreviousHash)?;
+
+    // Previous issuer must be none
+    block
+        .previous_issuer
+        .is_none()
+        .or_err(LocalVerifyGenesisBlockError::UnexpectedPreviousIssuer)?;
+
+    // Parameters
+    block
+        .parameters
+        .ok_or(LocalVerifyGenesisBlockError::MissingParameters)?;
+
+    // unit_base must be equal to zero
+    (block.unit_base == 0).or_err(LocalVerifyGenesisBlockError::NonZeroUnitBase {
+        unit_base: block.unit_base,
+    })?;
+
+    // time must be equal to median_time
+    (block.time == block.median_time).or_err(LocalVerifyGenesisBlockError::TimeError {
+        block_time: block.time,
+        median_time: block.median_time,
+    })?;
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use dubp_block_doc::BlockDocument;
+    use dubp_blocks_tests_tools::mocks::gen_mock_genesis_block_v10;
+    use dup_crypto::hashs::Hash;
+    use dup_crypto::keys::*;
+
+    #[test]
+    fn test_genesis_block_valid() {
+        let block = gen_mock_genesis_block_v10();
+        assert_eq!(
+            Ok(()),
+            local_validation_genesis_block(&BlockDocument::V10(block))
+        );
+    }
+
+    #[test]
+    fn test_genesis_block_wrong_number() {
+        let mut block = gen_mock_genesis_block_v10();
+        block.number = BlockNumber(1);
+
+        let expected = Err(LocalVerifyGenesisBlockError::NonZeroBlockNumber {
+            block_number: BlockNumber(1),
+        });
+        let actual = local_validation_genesis_block(&BlockDocument::V10(block));
+        assert_eq!(expected, actual);
+    }
+
+    #[test]
+    fn test_genesis_block_unexpected_dividend() {
+        let mut block = gen_mock_genesis_block_v10();
+        block.dividend = Some(10);
+
+        let expected = Err(LocalVerifyGenesisBlockError::UnexpectedDividend);
+        let actual = local_validation_genesis_block(&BlockDocument::V10(block));
+        assert_eq!(expected, actual);
+    }
+
+    #[test]
+    fn test_genesis_block_unexpected_previous_hash() {
+        let mut block = gen_mock_genesis_block_v10();
+        block.previous_hash = Some(
+            Hash::from_hex("000001144968D0C3516BE6225E4662F182E28956AF46DD7FB228E3D0F9413FEB")
+                .expect("invalid hash"),
+        );
+
+        let expected = Err(LocalVerifyGenesisBlockError::UnexpectedPreviousHash);
+        let actual = local_validation_genesis_block(&BlockDocument::V10(block));
+        assert_eq!(expected, actual);
+    }
+
+    #[test]
+    fn test_genesis_block_unexpected_previous_issuer() {
+        let mut block = gen_mock_genesis_block_v10();
+        block.previous_issuer = Some(PubKey::Ed25519(
+            ed25519::PublicKey::from_base58("D3krfq6J9AmfpKnS3gQVYoy7NzGCc61vokteTS8LJ4YH")
+                .expect("invalid pubkey"),
+        ));
+
+        let expected = Err(LocalVerifyGenesisBlockError::UnexpectedPreviousIssuer);
+        let actual = local_validation_genesis_block(&BlockDocument::V10(block));
+        assert_eq!(expected, actual);
+    }
+
+    #[test]
+    fn test_genesis_block_missing_parameters() {
+        let mut block = gen_mock_genesis_block_v10();
+        block.parameters = None;
+
+        let expected = Err(LocalVerifyGenesisBlockError::MissingParameters);
+        let actual = local_validation_genesis_block(&BlockDocument::V10(block));
+        assert_eq!(expected, actual);
+    }
+
+    #[test]
+    fn test_genesis_block_non_zero_unit_base() {
+        let mut block = gen_mock_genesis_block_v10();
+        block.unit_base = 3;
+
+        let expected = Err(LocalVerifyGenesisBlockError::NonZeroUnitBase { unit_base: 3 });
+        let actual = local_validation_genesis_block(&BlockDocument::V10(block));
+        assert_eq!(expected, actual);
+    }
+
+    #[test]
+    fn test_genesis_block_ntime_error() {
+        let mut block = gen_mock_genesis_block_v10();
+        block.time = 3;
+        block.median_time = 4;
+
+        let expected = Err(LocalVerifyGenesisBlockError::TimeError {
+            block_time: 3,
+            median_time: 4,
+        });
+        let actual = local_validation_genesis_block(&BlockDocument::V10(block));
+        assert_eq!(expected, actual);
+    }
+}
diff --git a/lib/modules/blockchain/blockchain/src/dubp/check/local/not_genesis.rs b/lib/modules/blockchain/blockchain/src/dubp/check/local/not_genesis.rs
new file mode 100644
index 0000000000000000000000000000000000000000..0277999b22713c1a840a5edb92b7c1dfbc8a0ccd
--- /dev/null
+++ b/lib/modules/blockchain/blockchain/src/dubp/check/local/not_genesis.rs
@@ -0,0 +1,157 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// 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/>.
+
+//! Verifies if a normal block verifies the local rules specific to normal blocks
+
+use dubp_block_doc::BlockDocument;
+use dubp_currency_params::CurrencyParameters;
+
+#[derive(Debug, Clone, PartialEq)]
+/// Local verification error specific to a not-genesis Block
+pub enum LocalVerifyNotGenesisBlockError {
+    /// Is Genesis block
+    IsGenesisBlock,
+    /// No previous hash is provided
+    MissingPreviousHash,
+    /// No previous issuer is provided
+    MissingPreviousIssuer,
+    /// Some Paramters are provided in the Block Document
+    UnexpectedParameters,
+    /// Block Time
+    BlockTime {
+        actual_block_time: u64,
+        lower_block_time_bound: u64,
+        upper_block_time_bound: u64,
+    },
+}
+
+/// Local verification of rules specific of a not genesis block
+pub fn local_validation_not_genesis_block(
+    block: &BlockDocument,
+    currency_parameters: CurrencyParameters,
+) -> Result<(), LocalVerifyNotGenesisBlockError> {
+    let BlockDocument::V10(block) = block;
+
+    // Provided block is a genesis block
+    if block.number.0 == 0 {
+        return Err(LocalVerifyNotGenesisBlockError::IsGenesisBlock);
+    }
+
+    // PreviousHash
+    block
+        .previous_hash
+        .ok_or(LocalVerifyNotGenesisBlockError::MissingPreviousHash)?;
+
+    // PreviousIssuer
+    block
+        .previous_issuer
+        .ok_or(LocalVerifyNotGenesisBlockError::MissingPreviousIssuer)?;
+
+    // Parameters
+    if block.parameters.is_some() {
+        return Err(LocalVerifyNotGenesisBlockError::UnexpectedParameters);
+    }
+
+    // Dates
+    let avg_gen_time = currency_parameters.avg_gen_time as f64;
+    let max_gen_time = (avg_gen_time * 1.189).ceil();
+    let median_time_blocks = currency_parameters.median_time_blocks as f64;
+    let max_acceleration = max_gen_time * median_time_blocks;
+    let max_acceleration = max_acceleration.ceil() as u64;
+    if block.time < block.median_time || block.median_time + max_acceleration < block.time {
+        return Err(LocalVerifyNotGenesisBlockError::BlockTime {
+            actual_block_time: block.time,
+            lower_block_time_bound: block.median_time,
+            upper_block_time_bound: block.median_time + max_acceleration,
+        });
+    }
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use dubp_block_doc::BlockDocument;
+    use dubp_blocks_tests_tools::mocks::block_params::gen_mock_currency_parameters;
+    use dubp_blocks_tests_tools::mocks::gen_mock_normal_block_v10;
+    use dubp_common_doc::BlockNumber;
+
+    #[test]
+    fn local_verify_normal_block() -> Result<(), LocalVerifyNotGenesisBlockError> {
+        let currency_params = gen_mock_currency_parameters();
+
+        // Normal Rules : IsGenesisBlock
+        let mut block = gen_mock_normal_block_v10();
+        block.number = BlockNumber(0);
+
+        let expected = Err(LocalVerifyNotGenesisBlockError::IsGenesisBlock);
+        let actual =
+            local_validation_not_genesis_block(&BlockDocument::V10(block), currency_params);
+        assert_eq!(expected, actual);
+
+        // Normal Rules : Missing Previous Hash
+        let mut block = gen_mock_normal_block_v10();
+        block.previous_hash = None;
+
+        let expected = Err(LocalVerifyNotGenesisBlockError::MissingPreviousHash);
+        let actual =
+            local_validation_not_genesis_block(&BlockDocument::V10(block), currency_params);
+        assert_eq!(expected, actual);
+
+        // Normal Rules : Missing Previous Hash
+        let mut block = gen_mock_normal_block_v10();
+        block.previous_hash = None;
+
+        let expected = Err(LocalVerifyNotGenesisBlockError::MissingPreviousHash);
+        let actual =
+            local_validation_not_genesis_block(&BlockDocument::V10(block), currency_params);
+        assert_eq!(expected, actual);
+
+        // Normal Rules : Missing Previous Issuer
+        let mut block = gen_mock_normal_block_v10();
+        block.previous_issuer = None;
+
+        let expected = Err(LocalVerifyNotGenesisBlockError::MissingPreviousIssuer);
+        let actual =
+            local_validation_not_genesis_block(&BlockDocument::V10(block), currency_params);
+        assert_eq!(expected, actual);
+
+        // Normal Rules : Unexpected Parameters
+        let mut block = gen_mock_normal_block_v10();
+        block.parameters =
+            Some(dubp_currency_params::genesis_block_params::v10::BlockV10Parameters::default());
+
+        let expected = Err(LocalVerifyNotGenesisBlockError::UnexpectedParameters);
+        let actual =
+            local_validation_not_genesis_block(&BlockDocument::V10(block), currency_params);
+        assert_eq!(expected, actual);
+
+        // Normal Rules : Block Time
+        let mut block = gen_mock_normal_block_v10();
+        block.time = 685_861;
+
+        let expected = Err(LocalVerifyNotGenesisBlockError::BlockTime {
+            actual_block_time: 685_861,
+            lower_block_time_bound: 1_522_683_184,
+            upper_block_time_bound: 1_522_695_084,
+        });
+        let actual =
+            local_validation_not_genesis_block(&BlockDocument::V10(block), currency_params);
+        assert_eq!(expected, actual);
+
+        Ok(())
+    }
+}
diff --git a/lib/modules/blockchain/blockchain/src/dubp/check/local/tx_doc.rs b/lib/modules/blockchain/blockchain/src/dubp/check/local/tx_doc.rs
new file mode 100644
index 0000000000000000000000000000000000000000..9f0dd8f94dc819dfa9ddb45c86272a7913ee3fd1
--- /dev/null
+++ b/lib/modules/blockchain/blockchain/src/dubp/check/local/tx_doc.rs
@@ -0,0 +1,216 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// 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/>.
+
+//! Verifies if transaction document verifies the local rules
+
+use dubp_common_doc::errors::DocumentSigsErr;
+use dubp_common_doc::traits::text::CompactTextDocument;
+use dubp_common_doc::traits::Document;
+use dubp_user_docs::documents::transaction::TransactionDocument;
+use durs_common_tools::traits::bool_ext::BoolExt;
+
+#[derive(Debug, PartialEq)]
+/// Transaction Document Error
+pub enum TransactionDocumentError {
+    /// Length is too long
+    TooLong {
+        expected_max_length: usize,
+        actual_length: usize,
+    },
+    /// There is no input
+    MissingInput,
+    /// Signature error    
+    TxSignatureError(DocumentSigsErr),
+}
+
+/// Local verification of a Tx Document
+pub fn local_verify_tx_doc(tx_doc: &TransactionDocument) -> Result<(), TransactionDocumentError> {
+    // A transaction in compact format must measure less than 100 lines
+    (tx_doc.as_compact_text().lines().count() < 100).or_err(TransactionDocumentError::TooLong {
+        expected_max_length: 100,
+        actual_length: tx_doc.as_compact_text().lines().count(),
+    })?;
+
+    // A transaction must have at least 1 input
+    (tx_doc.get_inputs().is_empty().not()).or_err(TransactionDocumentError::MissingInput)?;
+
+    // A transaction cannot have `SIG(INDEX)` unlocks with `INDEX >= ` issuers count.
+    // Question : règle à pas vérifier
+    /*if y.get_unlocks().len() >= y.issuers().len() {
+        return Err(TransactionDocumentError(SignatureIssuerError));
+    }*/
+
+    // Signatures count must be the same as issuers count
+    // It's alreeady checked by `tx_doc.verify_signatures()`
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // A transaction **must** have signatures matching its content **for each issuer**
+    // Signatures are ordered by issuer
+    // Signatures are made over the transaction's content, signatures excepted
+    ////////////////////////////////////////////////////////////////////////////////////
+    tx_doc
+        .verify_signatures()
+        .map_err(TransactionDocumentError::TxSignatureError)?;
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use dubp_common_doc::traits::DocumentBuilder;
+    use dubp_common_doc::Blockstamp;
+    use dubp_user_docs::documents::transaction::OutputIndex;
+    use dubp_user_docs::documents::transaction::TransactionDocumentBuilder;
+    use dubp_user_docs::documents::transaction::TransactionInput;
+    use dubp_user_docs::documents::transaction::TransactionInputUnlocks;
+    use dubp_user_docs::documents::transaction::TransactionOutput;
+    use dubp_user_docs::documents::transaction::TransactionUnlockProof;
+    use dubp_user_docs::documents::transaction::TxAmount;
+    use dubp_user_docs::documents::transaction::TxBase;
+    use dubp_user_docs_tests_tools::mocks::tx::gen_mock_tx_doc;
+    use dup_crypto::hashs::Hash;
+    use dup_crypto::keys::*;
+    use std::str::FromStr;
+
+    #[inline]
+    fn blockstamp() -> Blockstamp {
+        Blockstamp::from_string(
+            "0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
+        )
+        .expect("invalid blockstamp")
+    }
+
+    #[inline]
+    fn issuers() -> Vec<PubKey> {
+        let keypair = ed25519::KeyPairFromSeed32Generator::generate(
+            Seed32::from_base58("DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV")
+                .expect("invalid seed32"),
+        );
+        vec![PubKey::Ed25519(keypair.public_key())]
+    }
+
+    #[inline]
+    fn sig1() -> Sig {
+        Sig::Ed25519(ed25519::Signature::from_base64(
+            "cq86RugQlqAEyS8zFkB9o0PlWPSb+a6D/MEnLe8j+okyFYf/WzI6pFiBkQ9PSOVn5I0dwzVXg7Q4N1apMWeGAg==",
+        ).unwrap())
+    }
+
+    #[inline]
+    fn input1() -> TransactionInput {
+        TransactionInput::T(
+            TxAmount(950),
+            TxBase(0),
+            Hash::from_hex("2CF1ACD8FE8DC93EE39A1D55881C50D87C55892AE8E4DB71D4EBAB3D412AA8FD")
+                .expect("invalid hash"),
+            OutputIndex(1),
+        )
+    }
+
+    #[inline]
+    fn unlocks() -> Vec<TransactionInputUnlocks> {
+        vec![TransactionInputUnlocks {
+            index: 0,
+            unlocks: vec![TransactionUnlockProof::Sig(0)],
+        }]
+    }
+
+    #[inline]
+    fn outputs() -> Vec<TransactionOutput> {
+        vec![
+            TransactionOutput::from_str("10:0:SIG(FD9wujR7KABw88RyKEGBYRLz8PA6jzVCbcBAsrBXBqSa)")
+                .expect("fail to parse output !"),
+        ]
+    }
+
+    fn tx_builder<'a>(
+        blockstamp: &'a Blockstamp,
+        issuers: &'a Vec<PubKey>,
+        inputs: &'a Vec<TransactionInput>,
+        unlocks: &'a Vec<TransactionInputUnlocks>,
+        outputs: &'a Vec<TransactionOutput>,
+    ) -> TransactionDocumentBuilder<'a> {
+        TransactionDocumentBuilder {
+            currency: "duniter_unit_test_currency",
+            blockstamp,
+            locktime: &0,
+            issuers,
+            inputs,
+            unlocks,
+            outputs,
+            comment: "test",
+            hash: None,
+        }
+    }
+
+    #[test]
+    fn test_tx_valid() {
+        let tx = gen_mock_tx_doc();
+        assert_eq!(Ok(()), local_verify_tx_doc(&tx));
+    }
+
+    #[test]
+    fn test_tx_empty_inputs() {
+        let blockstamp = blockstamp();
+        let issuers = issuers();
+        let inputs = vec![];
+        let unlocks = unlocks();
+        let outputs = outputs();
+        let tx_builder = tx_builder(&blockstamp, &issuers, &inputs, &unlocks, &outputs);
+        let tx = tx_builder.build_with_signature(vec![sig1()]);
+
+        let expected = Err(TransactionDocumentError::MissingInput);
+        let actual = local_verify_tx_doc(&tx);
+        assert_eq!(expected, actual);
+    }
+
+    #[test]
+    fn test_tx_too_long() {
+        let blockstamp = blockstamp();
+        let issuers = issuers();
+        let inputs = vec![input1(); 100];
+        let unlocks = unlocks();
+        let outputs = outputs();
+        let tx_builder = tx_builder(&blockstamp, &issuers, &inputs, &unlocks, &outputs);
+        let tx = tx_builder.build_with_signature(vec![sig1()]);
+
+        let expected = Err(TransactionDocumentError::TooLong {
+            expected_max_length: 100,
+            actual_length: 107,
+        });
+        let actual = local_verify_tx_doc(&tx);
+        assert_eq!(expected, actual);
+    }
+
+    #[test]
+    fn test_tx_invalid_sig() {
+        let blockstamp = blockstamp();
+        let issuers = issuers();
+        let inputs = vec![input1(); 2];
+        let unlocks = unlocks();
+        let outputs = outputs();
+        let tx_builder = tx_builder(&blockstamp, &issuers, &inputs, &unlocks, &outputs);
+        let tx = tx_builder.build_with_signature(vec![sig1()]);
+
+        let expected = Err(TransactionDocumentError::TxSignatureError(
+            DocumentSigsErr::Invalid(maplit::hashmap![
+                0 => SigError::InvalidSig,
+            ]),
+        ));
+        let actual = local_verify_tx_doc(&tx);
+        assert_eq!(expected, actual);
+    }
+}
diff --git a/lib/modules/blockchain/blockchain/src/dubp/check/pow.rs b/lib/modules/blockchain/blockchain/src/dubp/check/pow.rs
new file mode 100644
index 0000000000000000000000000000000000000000..706498f1194b619753e9f2b1bd6f8ee0a69c865d
--- /dev/null
+++ b/lib/modules/blockchain/blockchain/src/dubp/check/pow.rs
@@ -0,0 +1,148 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// 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/>.
+
+//! Verify block pow
+
+use dup_crypto::hashs::Hash;
+use durs_common_tools::traits::bool_ext::BoolExt;
+
+static ZERO_STRING: &str = "0";
+
+/// Proof of Work error
+#[derive(Debug, PartialEq)]
+pub enum BlockPoWError {
+    /// Invalid pow_min
+    _InvalidPoWMin,
+    /// Invalid PoW pattern
+    InvalidHashPattern {
+        expected_pattern: String,
+        actual_hash: String,
+    },
+}
+
+pub fn verify_hash_pattern(hash: Hash, diffi: usize) -> Result<(), BlockPoWError> {
+    let hash_string = hash.to_hex();
+    let nb_zeros = diffi / 16;
+    let expected_pattern_last_hex_digit = 16 - (diffi % 16);
+    let repeated_zero_string = ZERO_STRING.repeat(nb_zeros);
+    let expected_pattern = if expected_pattern_last_hex_digit < 15 && nb_zeros < 64 {
+        let expected_pattern_last_char =
+            std::char::from_digit(expected_pattern_last_hex_digit as u32, 16)
+                .expect("expected_pattern_last_hex_digit is necessarily less than 16");
+        let expected_pattern = format!(
+            "{}[0-{}]*",
+            repeated_zero_string, expected_pattern_last_char
+        );
+        let actual_pattern_last_hex_digit = usize::from_str_radix(
+            hash_string
+                .get(nb_zeros..=nb_zeros)
+                .expect("Hash string is necessary greater than nb_zeros + 1."),
+            16,
+        )
+        .expect("Hash type guarantees a valid hexadecimal string.");
+        // remainder must be less than or equal to expected_end_pattern
+        (actual_pattern_last_hex_digit <= expected_pattern_last_hex_digit).or_err(
+            BlockPoWError::InvalidHashPattern {
+                expected_pattern: expected_pattern.clone(),
+                actual_hash: hash_string.clone(),
+            },
+        )?;
+        expected_pattern
+    } else {
+        repeated_zero_string.clone()
+    };
+    hash_string
+        .starts_with(&repeated_zero_string)
+        .or_err(BlockPoWError::InvalidHashPattern {
+            expected_pattern,
+            actual_hash: hash_string,
+        })?;
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+
+    use super::*;
+
+    #[test]
+    fn test_verify_hash_pattern() {
+        assert_eq!(
+            Ok(()),
+            verify_hash_pattern(
+                Hash::from_hex("000003619ACBF80298F074D8339175901425BC97EF528ED02EBD73CD4CA5C559")
+                    .expect("invalid hash"),
+                70
+            )
+        );
+        assert_eq!(
+            Ok(()),
+            verify_hash_pattern(
+                Hash::from_hex("000013619ACBF80298F074D8339175901425BC97EF528ED02EBD73CD4CA5C559")
+                    .expect("invalid hash"),
+                70
+            )
+        );
+        assert_eq!(
+            Err(BlockPoWError::InvalidHashPattern {
+                expected_pattern: "0000[0-a]*".to_owned(),
+                actual_hash: "0000B3619ACBF80298F074D8339175901425BC97EF528ED02EBD73CD4CA5C559"
+                    .to_owned(),
+            }),
+            verify_hash_pattern(
+                Hash::from_hex("0000B3619ACBF80298F074D8339175901425BC97EF528ED02EBD73CD4CA5C559")
+                    .expect("invalid hash"),
+                70
+            )
+        );
+        assert_eq!(
+            Err(BlockPoWError::InvalidHashPattern {
+                expected_pattern: "0000[0-a]*".to_owned(),
+                actual_hash: "000313619ACBF80298F074D8339175901425BC97EF528ED02EBD73CD4CA5C559"
+                    .to_owned(),
+            }),
+            verify_hash_pattern(
+                Hash::from_hex("000313619ACBF80298F074D8339175901425BC97EF528ED02EBD73CD4CA5C559")
+                    .expect("invalid hash"),
+                70
+            )
+        );
+        assert_eq!(
+            Err(BlockPoWError::InvalidHashPattern {
+                expected_pattern: "00000".to_owned(),
+                actual_hash: "000313619ACBF80298F074D8339175901425BC97EF528ED02EBD73CD4CA5C559"
+                    .to_owned(),
+            }),
+            verify_hash_pattern(
+                Hash::from_hex("000313619ACBF80298F074D8339175901425BC97EF528ED02EBD73CD4CA5C559")
+                    .expect("invalid hash"),
+                80
+            )
+        );
+        assert_eq!(
+            Err(BlockPoWError::InvalidHashPattern {
+                expected_pattern: "0000".to_owned(),
+                actual_hash: "000313619ACBF80298F074D8339175901425BC97EF528ED02EBD73CD4CA5C559"
+                    .to_owned(),
+            }),
+            verify_hash_pattern(
+                Hash::from_hex("000313619ACBF80298F074D8339175901425BC97EF528ED02EBD73CD4CA5C559")
+                    .expect("invalid hash"),
+                65
+            )
+        );
+    }
+}
diff --git a/lib/modules/blockchain/blockchain/src/dunp/receiver.rs b/lib/modules/blockchain/blockchain/src/dunp/receiver.rs
index f3d640fc1c45d7d789441940b69c9a4671d44cba..6277d7a345095cc9ed5b970699558e353064f44f 100644
--- a/lib/modules/blockchain/blockchain/src/dunp/receiver.rs
+++ b/lib/modules/blockchain/blockchain/src/dunp/receiver.rs
@@ -108,8 +108,8 @@ pub fn receive_blocks(bc: &mut BlockchainModule, blocks: Vec<BlockDocument>) {
                     }
                 },
                 Err(e) => match e {
-                    BlockError::VerifyBlockHashError(_) | BlockError::InvalidBlock(_) => {
-                        warn!("InvalidBlock(#{})", blockstamp.id.0);
+                    BlockError::InvalidBlock(e) => {
+                        warn!("InvalidBlock #{}: {:?}", blockstamp.id.0, e);
                         crate::events::sent::send_event(
                             bc,
                             &BlockchainEvent::RefusedBlock(blockstamp),
diff --git a/lib/modules/blockchain/blockchain/src/fork/rollback.rs b/lib/modules/blockchain/blockchain/src/fork/rollback.rs
index 8aacf3b83eb8bde3289b6ba518951e58897dc52f..27b155896e474e6a516373e318a6eef0dd5b2a9e 100644
--- a/lib/modules/blockchain/blockchain/src/fork/rollback.rs
+++ b/lib/modules/blockchain/blockchain/src/fork/rollback.rs
@@ -127,7 +127,7 @@ pub fn apply_rollback(bc: &mut BlockchainModule, new_bc_branch: Vec<Blockstamp>)
                     Err(e) => {
                         new_branch_is_valid = false;
                         bc.invalid_forks.insert(*blockstamp);
-                        info!(
+                        warn!(
                             "Blockchain: abort rollback: block {} is invalid: {:?}",
                             blockstamp, e
                         );
diff --git a/lib/tests-tools/blocks-tests-tools/src/mocks.rs b/lib/tests-tools/blocks-tests-tools/src/mocks.rs
index 7a1fba293191a19bfd8399006c0cf96f925b9796..ad83d12825b5f1a4bf5ae820596d708caabbff93 100644
--- a/lib/tests-tools/blocks-tests-tools/src/mocks.rs
+++ b/lib/tests-tools/blocks-tests-tools/src/mocks.rs
@@ -15,13 +15,21 @@
 
 //! Mocks for projects use dubp-block-doc
 
+pub mod block_params;
+
 use dubp_block_doc::block::BlockDocumentTrait;
 use dubp_block_doc::{BlockDocument, BlockDocumentV10};
 use dubp_common_doc::blockstamp::Blockstamp;
+use dubp_common_doc::parser::TextDocumentParser;
+use dubp_common_doc::traits::text::*;
 use dubp_common_doc::{BlockHash, BlockNumber};
+use dubp_currency_params::genesis_block_params::v10::BlockV10Parameters;
 use dubp_currency_params::CurrencyName;
+use dubp_user_docs::documents::certification::*;
+use dubp_user_docs::documents::transaction::*;
+use dup_crypto::bases::b16::str_hex_to_32bytes;
 use dup_crypto::hashs::Hash;
-use dup_crypto::keys::{PubKey, Signator};
+use dup_crypto::keys::{ed25519, PubKey, PublicKey, Sig, Signator, Signature};
 
 /// Generate n mock blockstamps
 pub fn generate_blockstamps(n: usize) -> Vec<Blockstamp> {
@@ -67,6 +75,7 @@ pub fn gen_empty_timed_issued_hashed_block_v10(
     signator: &dup_crypto::keys::SignatorEnum,
 ) -> BlockDocumentV10 {
     let mut block = gen_empty_block_v10(block_number);
+    block.time = time;
     block.median_time = time;
     block.issuers = vec![signator.public_key()];
     block.previous_issuer = Some(previous_issuer);
@@ -124,3 +133,105 @@ fn gen_empty_block_v10(block_number: BlockNumber) -> BlockDocumentV10 {
         inner_hash: None,
     }
 }
+
+/// Generate mock block which is not a genesis block
+pub fn gen_mock_normal_block_v10() -> BlockDocumentV10 {
+    let cert1 = CertificationDocumentParser::parse("Version: 10
+Type: Certification
+Currency: g1
+Issuer: 6TAzLWuNcSqgNDNpAutrKpPXcGJwy1ZEMeVvZSZNs2e3
+IdtyIssuer: CYPsYTdt87Tx6cCiZs9KD4jqPgYxbcVEqVZpRgJ9jjoV
+IdtyUniqueID: PascaleM
+IdtyTimestamp: 97401-0000003821911909F98519CC773D2D3E5CFE3D5DBB39F4F4FF33B96B4D41800E
+IdtySignature: QncUVXxZ2NfARjdJOn6luILvDuG1NuK9qSoaU4CST2Ij8z7oeVtEgryHl+EXOjSe6XniALsCT0gU8wtadcA/Cw==
+CertTimestamp: 106669-000003682E6FE38C44433DCE92E8B2A26C69B6D7867A2BAED231E788DDEF4251
+UmseG2XKNwKcY8RFi6gUCT91udGnnNmSh7se10J1jeRVlwf+O2Tyb2Cccot9Dt7BO4+Kx2P6vFJB3oVGGHMxBA==").expect("Fail to parse cert1");
+    let CertificationDocument::V10(cert1) = cert1;
+
+    let tx1 = dubp_user_docs_tests_tools::mocks::tx::gen_mock_tx_doc();
+    let tx2 = TransactionDocumentParser::parse("Version: 10
+Type: Transaction
+Currency: g1
+Blockstamp: 107982-000001242F6DA51C06A915A96C58BAA37AB3D1EB51F6E1C630C707845ACF764B
+Locktime: 0
+Issuers:
+8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3
+Inputs:
+1002:0:D:8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3:106614
+Unlocks:
+0:SIG(0)
+Outputs:
+1002:0:SIG(78ZwwgpgdH5uLZLbThUQH7LKwPgjMunYfLiCfUCySkM8)
+Comment: DU symbolique pour demander le codage de nouvelles fonctionnalites cf. https://forum.monnaie-libre.fr/t/creer-de-nouvelles-fonctionnalites-dans-cesium-les-autres-applications/2025  Merci
+a9PHPuSfw7jW8FRQHXFsGi/bnLjbtDnTYvEVgUC9u0WlR7GVofa+Xb+l5iy6NwuEXiwvueAkf08wPVY8xrNcCg==").expect("Fail to parse tx2");
+
+    BlockDocumentV10 {
+            nonce: 10_300_000_018_323,
+            version: 10,
+            number: BlockNumber(107_984),
+            pow_min: 88,
+            time: 1_522_685_861,
+            median_time: 1_522_683_184,
+            members_count: 896,
+            monetary_mass: 140_469_765,
+            unit_base: 0,
+            issuers_count: 42,
+            issuers_frame: 211,
+            issuers_frame_var: 0,
+            currency: CurrencyName(String::from("g1")),
+            issuers: vec![PubKey::Ed25519(ed25519::PublicKey::from_base58("DA4PYtXdvQqk1nCaprXH52iMsK5Ahxs1nRWbWKLhpVkQ").unwrap())],
+            signatures: vec![Sig::Ed25519(ed25519::Signature::from_base64("92id58VmkhgVNee4LDqBGSm8u/ooHzAD67JM6fhAE/CV8LCz7XrMF1DvRl+eRpmlaVkp6I+Iy8gmZ1WUM5C8BA==").unwrap())],
+            hash: None,
+            parameters: None,
+            previous_hash: Some(Hash::from_hex("000001144968D0C3516BE6225E4662F182E28956AF46DD7FB228E3D0F9413FEB").expect("fail to parse previous_hash")),
+            previous_issuer: Some(PubKey::Ed25519(ed25519::PublicKey::from_base58("D3krfq6J9AmfpKnS3gQVYoy7NzGCc61vokteTS8LJ4YH").unwrap())),
+            inner_hash: Some(Hash(
+                    str_hex_to_32bytes(
+                        "C8AB69E33ECE2612EADC7AB30D069B1F1A3D8C95EBBFD50DE583AC8E3666CCA1",
+                    ).unwrap() )),
+            dividend: None,
+            identities: Vec::new(),
+            joiners: Vec::new(),
+            actives: Vec::new(),
+            leavers: Vec::new(),
+            revoked: Vec::new(),
+            excluded: Vec::new(),
+            certifications: vec![TextDocumentFormat::Complete(cert1)],
+            transactions: vec![tx1, tx2],
+        }
+}
+
+/// Generate a mock genesis block
+pub fn gen_mock_genesis_block_v10() -> BlockDocumentV10 {
+    BlockDocumentV10 {
+            nonce: 0,
+            version: 10,
+            number: BlockNumber(0),
+            pow_min: 0,
+            time: 0,
+            median_time: 0,
+            members_count: 0,
+            monetary_mass: 0,
+            unit_base: 0,
+            issuers_count: 0,
+            issuers_frame: 0,
+            issuers_frame_var: 0,
+            currency: CurrencyName(String::from("g1")),
+            issuers: vec![PubKey::Ed25519(ed25519::PublicKey::from_base58("DA4PYtXdvQqk1nCaprXH52iMsK5Ahxs1nRWbWKLhpVkQ").unwrap())],
+            signatures: vec![Sig::Ed25519(ed25519::Signature::from_base64("92id58VmkhgVNee4LDqBGSm8u/ooHzAD67JM6fhAE/CV8LCz7XrMF1DvRl+eRpmlaVkp6I+Iy8gmZ1WUM5C8BA==").unwrap())],
+            hash: None,
+            parameters: Some(BlockV10Parameters::default()),
+            previous_hash: None,
+            previous_issuer: None,
+            inner_hash: None,
+            dividend: None,
+            identities: Vec::new(),
+            joiners: Vec::new(),
+            actives: Vec::new(),
+            leavers: Vec::new(),
+            revoked: Vec::new(),
+            excluded: Vec::new(),
+            certifications: Vec::new(),
+            transactions: Vec::new(),
+        }
+}
diff --git a/lib/tests-tools/blocks-tests-tools/src/mocks/block_params.rs b/lib/tests-tools/blocks-tests-tools/src/mocks/block_params.rs
new file mode 100644
index 0000000000000000000000000000000000000000..6c0813d1fc43b157439136f110b1fc30438b7608
--- /dev/null
+++ b/lib/tests-tools/blocks-tests-tools/src/mocks/block_params.rs
@@ -0,0 +1,49 @@
+//  Copyright (C) 2019  Éloïs SANCHEZ
+//
+// 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/>.
+
+//! Mocks for projects use dubp-block-doc
+
+use dubp_currency_params::CurrencyParameters;
+
+/// Generate mock currency parameters
+pub fn gen_mock_currency_parameters() -> CurrencyParameters {
+    CurrencyParameters {
+        protocol_version: 10,
+        c: 0.004,               // UD target growth rate (see Relative Theorie of Money)
+        dt: 1000,               // Duration between the creation of two UD (in seconds)
+        ud0: 10,                // Amount of the initial UD
+        sig_period: 10000, // Minimum duration between the writing of 2 certifications from the same issuer (in seconds)
+        sig_renew_period: 1000, // Minimum duration between two renewals of the same certification
+        sig_stock: 100, // Maximum number of active certifications at the same time (for the same issuer)
+        sig_window: 100,
+        sig_validity: 100,
+        sig_qty: 100,
+        idty_window: 100,
+        ms_window: 100,
+        tx_window: 100,
+        x_percent: 0.8,
+        ms_validity: 100,
+        ms_period: 100,
+        step_max: 100,
+        median_time_blocks: 100,
+        avg_gen_time: 100,
+        dt_diff_eval: 100,
+        percent_rot: 0.5,
+        ud_time0: 100,
+        ud_reeval_time0: 100,
+        dt_reeval: 100,
+        fork_window_size: 100,
+    }
+}
diff --git a/lib/tests-tools/user-docs-tests-tools/Cargo.toml b/lib/tests-tools/user-docs-tests-tools/Cargo.toml
index a558a3edde3599ef080ed3fd991c76ae3c1175ca..5906780fd37c1a1663874a7abbcb98ce41a64f90 100644
--- a/lib/tests-tools/user-docs-tests-tools/Cargo.toml
+++ b/lib/tests-tools/user-docs-tests-tools/Cargo.toml
@@ -13,6 +13,7 @@ edition = "2018"
 path = "src/lib.rs"
 
 [dependencies]
+dubp-block-doc = { path = "../../dubp/block-doc"} #, version = "0.1.0" }
 dubp-common-doc = { path = "../../dubp/common-doc"} #, version = "0.1.0" }
 dubp-currency-params = { path = "../../dubp/currency-params" }
 dubp-user-docs = { path = "../../dubp/user-docs" }
diff --git a/lib/tests-tools/user-docs-tests-tools/src/mocks/tx.rs b/lib/tests-tools/user-docs-tests-tools/src/mocks/tx.rs
index 5ed6cbcf637f899d10bafb63167d384fd3ac773f..f6abdd0beebafdf3e3641183361c5826da321a38 100644
--- a/lib/tests-tools/user-docs-tests-tools/src/mocks/tx.rs
+++ b/lib/tests-tools/user-docs-tests-tools/src/mocks/tx.rs
@@ -15,6 +15,7 @@
 
 //! Mocks for projects use dubp-user-docs
 
+use dubp_common_doc::parser::TextDocumentParser;
 use dubp_common_doc::traits::DocumentBuilder;
 use dubp_common_doc::Blockstamp;
 use dubp_user_docs::documents::transaction::*;
@@ -55,3 +56,41 @@ pub fn first_g1_tx_doc() -> TransactionDocument {
                 ed25519::Signature::from_base64("fAH5Gor+8MtFzQZ++JaJO6U8JJ6+rkqKtPrRr/iufh3MYkoDGxmjzj6jCADQL+hkWBt8y8QzlgRkz0ixBcKHBw==").expect("Fail to parse sig !")
             )])
 }
+
+/// Generate mock transaction document
+pub fn gen_mock_tx_doc() -> TransactionDocument {
+    TransactionDocumentParser::parse("Version: 10
+Type: Transaction
+Currency: g1
+Blockstamp: 107982-000001242F6DA51C06A915A96C58BAA37AB3D1EB51F6E1C630C707845ACF764B
+Locktime: 0
+Issuers:
+8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3
+Inputs:
+1002:0:D:8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3:106345
+Unlocks:
+0:SIG(0)
+Outputs:
+1002:0:SIG(CitdnuQgZ45tNFCagay7Wh12gwwHM8VLej1sWmfHWnQX)
+Comment: DU symbolique pour demander le codage de nouvelles fonctionnalites cf. https://forum.monnaie-libre.fr/t/creer-de-nouvelles-fonctionnalites-dans-cesium-les-autres-applications/2025  Merci
+T0LlCcbIn7xDFws48H8LboN6NxxwNXXTovG4PROLf7tkUAueHFWjfwZFKQXeZEHxfaL1eYs3QspGtLWUHPRVCQ==").expect("Fail to parse tx1")
+}
+
+/// Generate mock transaction document with wrong version
+pub fn gen_mock_tx_doc_wrong_version() -> TransactionDocument {
+    TransactionDocumentParser::parse("Version: 12
+Type: Transaction
+Currency: g1
+Blockstamp: 107982-000001242F6DA51C06A915A96C58BAA37AB3D1EB51F6E1C630C707845ACF764B
+Locktime: 0
+Issuers:
+8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3
+Inputs:
+1002:0:D:8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3:106345
+Unlocks:
+0:SIG(0)
+Outputs:
+1002:0:SIG(CitdnuQgZ45tNFCagay7Wh12gwwHM8VLej1sWmfHWnQX)
+Comment: DU symbolique pour demander le codage de nouvelles fonctionnalites cf. https://forum.monnaie-libre.fr/t/creer-de-nouvelles-fonctionnalites-dans-cesium-les-autres-applications/2025  Merci
+T0LlCcbIn7xDFws48H8LboN6NxxwNXXTovG4PROLf7tkUAueHFWjfwZFKQXeZEHxfaL1eYs3QspGtLWUHPRVCQ==").expect("Fail to parse tx1")
+}
diff --git a/lib/tools/common-tools/src/traits/bool_ext.rs b/lib/tools/common-tools/src/traits/bool_ext.rs
new file mode 100644
index 0000000000000000000000000000000000000000..908b57c0b125b80b85d1aad11424e3361e43e18d
--- /dev/null
+++ b/lib/tools/common-tools/src/traits/bool_ext.rs
@@ -0,0 +1,49 @@
+//  Copyright (C) 2019  Éloïs SANCHEZ
+//
+// 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/>.
+
+//! Trait AsResult.
+
+/// Transform any type to Result
+pub trait BoolExt {
+    /// Transform any type to result<(), E>
+    fn or_err<E>(self, err: E) -> Result<(), E>;
+    /// Transform any type to result<T, E>
+    fn as_result<T, E>(self, ok: T, err: E) -> Result<T, E>;
+    /// Reverse bool
+    fn not(self) -> bool;
+}
+
+impl BoolExt for bool {
+    #[inline]
+    fn or_err<E>(self, err: E) -> Result<(), E> {
+        if self {
+            Ok(())
+        } else {
+            Err(err)
+        }
+    }
+    #[inline]
+    fn as_result<T, E>(self, ok: T, err: E) -> Result<T, E> {
+        if self {
+            Ok(ok)
+        } else {
+            Err(err)
+        }
+    }
+    #[inline]
+    fn not(self) -> bool {
+        !self
+    }
+}
diff --git a/lib/tools/common-tools/src/traits/mod.rs b/lib/tools/common-tools/src/traits/mod.rs
index f3f2049fbe4ef765faf8ff48f3aa00b5700d93ed..757fcc097538f2f88e40ce6aa7c69b658bdbaed6 100644
--- a/lib/tools/common-tools/src/traits/mod.rs
+++ b/lib/tools/common-tools/src/traits/mod.rs
@@ -15,4 +15,5 @@
 
 //! Common rust traits for DURS project.
 
+pub mod bool_ext;
 pub mod merge;