diff --git a/lib/modules/blockchain/blockchain-dal/src/entities/block.rs b/lib/modules/blockchain/blockchain-dal/src/entities/block.rs
index cc4ca8b09d778031f48f99611045d92ec583fd9c..b22ade1daf8031c65e13e5010e327bf3803bea9d 100644
--- a/lib/modules/blockchain/blockchain-dal/src/entities/block.rs
+++ b/lib/modules/blockchain/blockchain-dal/src/entities/block.rs
@@ -14,7 +14,7 @@
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 use crate::*;
-use dubp_documents::documents::block::BlockDocument;
+use dubp_documents::documents::block::{BlockDocument, BlockDocumentTrait};
 use dubp_documents::Document;
 use dubp_documents::{BlockNumber, Blockstamp};
 use durs_wot::NodeId;
diff --git a/lib/modules/blockchain/blockchain-dal/src/readers/block.rs b/lib/modules/blockchain/blockchain-dal/src/readers/block.rs
index a9414bc44e780bcd320c689ad410d2b945c6fbda..8df1aa1bb6954bde68076ba2f2752df2876368e6 100644
--- a/lib/modules/blockchain/blockchain-dal/src/readers/block.rs
+++ b/lib/modules/blockchain/blockchain-dal/src/readers/block.rs
@@ -14,7 +14,7 @@
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 use crate::*;
-use dubp_documents::documents::block::BlockDocument;
+use dubp_documents::documents::block::{BlockDocument, BlockDocumentTrait};
 use dubp_documents::Document;
 use dubp_documents::{BlockHash, BlockNumber, Blockstamp};
 use dup_crypto::keys::*;
@@ -42,7 +42,7 @@ pub fn get_block_hash(
 ) -> Result<Option<BlockHash>, DALError> {
     Ok(db.read(|db| {
         if let Some(dal_block) = db.get(&block_number) {
-            dal_block.block.hash
+            dal_block.block.hash()
         } else {
             None
         }
@@ -86,7 +86,7 @@ pub fn already_have_block(
     } else {
         return Ok(blockchain_db.read(|db| {
             if let Some(dal_block) = db.get(&blockstamp.id) {
-                if dal_block.block.hash.unwrap_or_default() == blockstamp.hash {
+                if dal_block.block.hash().unwrap_or_default() == blockstamp.hash {
                     return true;
                 }
             }
@@ -151,10 +151,11 @@ pub fn get_current_frame(
     current_block: &DALBlock,
     db: &BinDB<LocalBlockchainV10Datas>,
 ) -> Result<HashMap<PubKey, usize>, DALError> {
-    let frame_begin = current_block.block.number.0 - current_block.block.issuers_frame as u32;
+    let frame_begin =
+        current_block.block.number().0 - current_block.block.current_frame_size() as u32;
     Ok(db.read(|db| {
         let mut current_frame: HashMap<PubKey, usize> = HashMap::new();
-        for block_number in frame_begin..current_block.block.number.0 {
+        for block_number in frame_begin..current_block.block.number().0 {
             let issuer = db
                 .get(&BlockNumber(block_number))
                 .unwrap_or_else(|| fatal_error!("Fail to get block #{} !", block_number))
diff --git a/lib/modules/blockchain/blockchain-dal/src/readers/currency_params.rs b/lib/modules/blockchain/blockchain-dal/src/readers/currency_params.rs
index 44dec3e618a6825def8bbe750daad512091d51d2..2be4b61dff636d7a413db27956c5fd7c937923e7 100644
--- a/lib/modules/blockchain/blockchain-dal/src/readers/currency_params.rs
+++ b/lib/modules/blockchain/blockchain-dal/src/readers/currency_params.rs
@@ -14,7 +14,8 @@
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 use crate::*;
-use dubp_documents::documents::block::BlockDocument;
+use dubp_documents::documents::block::{BlockDocument, BlockDocumentTrait};
+use dubp_documents::Document;
 use dup_currency_params::db::write_currency_params;
 use dup_currency_params::genesis_block_params::GenesisBlockParams;
 use dup_currency_params::CurrencyParameters;
@@ -25,17 +26,26 @@ pub fn get_and_write_currency_params(
     db_path: &PathBuf,
     genesis_block: &BlockDocument,
 ) -> CurrencyParameters {
-    if genesis_block.number.0 != 0 {
+    if genesis_block.number().0 != 0 {
         fatal_error!("The genesis block must have number equal to zero !");
-    } else if genesis_block.parameters.is_none() {
-        fatal_error!("The genesis block must have parameters !");
-    } else if let Err(e) = write_currency_params(
-        db_path.clone(),
-        genesis_block.currency.clone(),
-        GenesisBlockParams::V10(unwrap!(genesis_block.parameters)),
-    ) {
-        fatal_error!("Fail to write currency parameters: {}", e);
-    } else {
-        CurrencyParameters::from((&genesis_block.currency, unwrap!(genesis_block.parameters)))
+    }
+
+    match genesis_block {
+        BlockDocument::V10(genesis_block_v10) => {
+            if genesis_block_v10.parameters.is_none() {
+                fatal_error!("The genesis block must have parameters !");
+            } else if let Err(e) = write_currency_params(
+                db_path.clone(),
+                genesis_block_v10.currency().into(),
+                GenesisBlockParams::V10(unwrap!(genesis_block_v10.parameters)),
+            ) {
+                fatal_error!("Fail to write currency parameters: {}", e);
+            } else {
+                CurrencyParameters::from((
+                    &genesis_block_v10.currency().into(),
+                    unwrap!(genesis_block_v10.parameters),
+                ))
+            }
+        }
     }
 }
diff --git a/lib/modules/blockchain/blockchain-dal/src/tools.rs b/lib/modules/blockchain/blockchain-dal/src/tools.rs
index 7554cdd84d40365b2a214aab71acd1512dd0302e..dc12918b2afc099f838917e4be9a220ed1b09407 100644
--- a/lib/modules/blockchain/blockchain-dal/src/tools.rs
+++ b/lib/modules/blockchain/blockchain-dal/src/tools.rs
@@ -14,6 +14,7 @@
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 use crate::entities::block::DALBlock;
+use dubp_documents::documents::block::BlockDocumentTrait;
 use dup_crypto::keys::PubKey;
 use durs_common_tools::fatal_error;
 use durs_wot::operations::centrality::{CentralitiesCalculator, UlrikBrandesCentralityCalculator};
@@ -151,12 +152,12 @@ pub fn compute_median_issuers_frame<S: std::hash::BuildHasher>(
         current_frame_vec.sort_unstable();
 
         // Calculate median
-        let mut median_index = match current_block.block.issuers_count % 2 {
-            1 => (current_block.block.issuers_count / 2) + 1,
-            _ => current_block.block.issuers_count / 2,
+        let mut median_index = match current_block.block.issuers_count() % 2 {
+            1 => (current_block.block.issuers_count() / 2) + 1,
+            _ => current_block.block.issuers_count() / 2,
         };
-        if median_index >= current_block.block.issuers_count {
-            median_index = current_block.block.issuers_count - 1;
+        if median_index >= current_block.block.issuers_count() {
+            median_index = current_block.block.issuers_count() - 1;
         }
         current_frame_vec[median_index]
 
diff --git a/lib/modules/blockchain/blockchain-dal/src/writers/block.rs b/lib/modules/blockchain/blockchain-dal/src/writers/block.rs
index ecbf6ddea5ee51235c44e2ceadc9c6b2c8797235..47a27058f9cb376de986c68cacd7b801bffac153 100644
--- a/lib/modules/blockchain/blockchain-dal/src/writers/block.rs
+++ b/lib/modules/blockchain/blockchain-dal/src/writers/block.rs
@@ -16,6 +16,7 @@
 use crate::entities::block::DALBlock;
 use crate::*;
 use crate::{BinDB, DALError, LocalBlockchainV10Datas};
+use dubp_documents::documents::block::BlockDocumentTrait;
 use dubp_documents::Document;
 use unwrap::unwrap;
 
@@ -27,7 +28,7 @@ pub fn insert_new_head_block(
 ) -> Result<(), DALError> {
     // Insert head block in blockchain
     blockchain_db.write(|db| {
-        db.insert(dal_block.block.number, dal_block.clone());
+        db.insert(dal_block.block.number(), dal_block.clone());
     })?;
 
     // Insert head block in fork tree
@@ -56,7 +57,7 @@ pub fn insert_new_fork_block(forks_dbs: &ForksDBs, dal_block: DALBlock) -> Resul
     if crate::writers::fork_tree::insert_new_fork_block(
         &forks_dbs.fork_tree_db,
         dal_block.block.blockstamp(),
-        unwrap!(dal_block.block.previous_hash),
+        unwrap!(dal_block.block.previous_hash()),
     )? {
         // Insert in ForksBlocks
         forks_dbs.fork_blocks_db.write(|db| {
diff --git a/lib/modules/blockchain/blockchain-dal/src/writers/requests.rs b/lib/modules/blockchain/blockchain-dal/src/writers/requests.rs
index 22fb9a3fc5a8c40b50c868e9d19634285ef4d2f1..be8610a5591634531aed0d601189531f254d8740 100644
--- a/lib/modules/blockchain/blockchain-dal/src/writers/requests.rs
+++ b/lib/modules/blockchain/blockchain-dal/src/writers/requests.rs
@@ -17,7 +17,7 @@ use crate::entities::block::DALBlock;
 use crate::entities::sources::SourceAmount;
 use crate::writers::transaction::DALTxV10;
 use crate::*;
-use dubp_documents::documents::block::BlockDocument;
+use dubp_documents::documents::block::{BlockDocument, BlockDocumentTrait};
 use dubp_documents::documents::certification::CompactCertificationDocument;
 use dubp_documents::documents::identity::IdentityDocument;
 use dubp_documents::Blockstamp;
@@ -74,7 +74,7 @@ impl BlocksDBsWriteQuery {
                 } else {
                     // Insert block in blockchain
                     blockchain_db.write(|db| {
-                        db.insert(dal_block.block.number, dal_block);
+                        db.insert(dal_block.block.number(), dal_block);
                     })?;
                 }
             }
@@ -82,7 +82,7 @@ impl BlocksDBsWriteQuery {
                 trace!("BlocksDBsWriteQuery::WriteBlock...");
                 // Remove block in blockchain
                 blockchain_db.write(|db| {
-                    db.remove(&dal_block.block.number);
+                    db.remove(&dal_block.block.number());
                 })?;
                 trace!("BlocksDBsWriteQuery::WriteBlock...finish");
             }
diff --git a/lib/modules/blockchain/blockchain/src/dbex.rs b/lib/modules/blockchain/blockchain/src/dbex.rs
index e74145a6fad65960f6c5f9c0dcee62b58f23749c..ab4767a4e5348b013d2b91ef649ab4c7f5767486 100644
--- a/lib/modules/blockchain/blockchain/src/dbex.rs
+++ b/lib/modules/blockchain/blockchain/src/dbex.rs
@@ -14,6 +14,7 @@
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 use crate::*;
+use dubp_documents::documents::block::BlockDocumentTrait;
 use dubp_documents::documents::transaction::*;
 use dup_crypto::keys::*;
 use durs_wot::data::rusty::RustyWebOfTrust;
@@ -242,9 +243,9 @@ pub fn dbex_wot(profile_path: PathBuf, csv: bool, query: &DBExWotQuery) {
             let (current_bc_time, blocks_times): (u64, HashMap<BlockNumber, u64>) = blockchain_db
                 .read(|db| {
                     (
-                        db[&BlockNumber(db.len() as u32 - 1)].block.median_time,
+                        db[&BlockNumber(db.len() as u32 - 1)].block.common_time(),
                         db.iter()
-                            .map(|(block_id, dal_block)| (*block_id, dal_block.block.median_time))
+                            .map(|(block_id, dal_block)| (*block_id, dal_block.block.common_time()))
                             .collect(),
                     )
                 })
diff --git a/lib/modules/blockchain/blockchain/src/dubp/apply/mod.rs b/lib/modules/blockchain/blockchain/src/dubp/apply/mod.rs
index 058865a0fc459f4d4c40729d583f1e7818547267..3cef4d90d013e789be6015cf410b4f30eb081b9b 100644
--- a/lib/modules/blockchain/blockchain/src/dubp/apply/mod.rs
+++ b/lib/modules/blockchain/blockchain/src/dubp/apply/mod.rs
@@ -15,7 +15,7 @@
 
 //! Sub-module that applies the content of a block to the indexes of the local blockchain.
 
-use dubp_documents::documents::block::BlockDocument;
+use dubp_documents::documents::block::{BlockDocument, BlockDocumentTrait, BlockDocumentV10};
 use dubp_documents::documents::transaction::{TxAmount, TxBase};
 use dubp_documents::{BlockNumber, Document};
 use dup_crypto::keys::*;
@@ -44,8 +44,22 @@ pub enum ApplyValidBlockError {
     RevokeUnknowNodeId,
 }
 
+#[inline]
 pub fn apply_valid_block<W: WebOfTrust>(
-    mut block: BlockDocument,
+    block: BlockDocument,
+    wot_index: &mut HashMap<PubKey, NodeId>,
+    wot_db: &BinDB<W>,
+    expire_certs: &HashMap<(NodeId, NodeId), BlockNumber>,
+) -> Result<ValidBlockApplyReqs, ApplyValidBlockError> {
+    match block {
+        BlockDocument::V10(block_v10) => {
+            apply_valid_block_v10(block_v10, wot_index, wot_db, expire_certs)
+        }
+    }
+}
+
+pub fn apply_valid_block_v10<W: WebOfTrust>(
+    mut block: BlockDocumentV10,
     wot_index: &mut HashMap<PubKey, NodeId>,
     wot_db: &BinDB<W>,
     expire_certs: &HashMap<(NodeId, NodeId), BlockNumber>,
@@ -270,7 +284,7 @@ pub fn apply_valid_block<W: WebOfTrust>(
     // Create DALBlock
     block.reduce();
     let dal_block = DALBlock {
-        block,
+        block: BlockDocument::V10(block),
         expire_certs: Some(expire_certs.clone()),
     };
     // Return DBs requests
diff --git a/lib/modules/blockchain/blockchain/src/dubp/check/hashs.rs b/lib/modules/blockchain/blockchain/src/dubp/check/hashs.rs
index bee2034936d8f4b70c7c4f1c65018e2c0663c5df..81a9d7850b5b4f50a48d4c1370c6ec02610e3342 100644
--- a/lib/modules/blockchain/blockchain/src/dubp/check/hashs.rs
+++ b/lib/modules/blockchain/blockchain/src/dubp/check/hashs.rs
@@ -16,28 +16,21 @@
 //! Verify block inner hash and block hash
 
 use crate::VerifyBlockHashsError;
-use dubp_documents::documents::block::BlockDocument;
-use durs_common_tools::fatal_error;
+use dubp_documents::documents::block::{BlockDocument, BlockDocumentTrait};
 
 /// Verify block hashs
 pub fn verify_block_hashs(block_doc: &BlockDocument) -> Result<(), VerifyBlockHashsError> {
-    trace!("complete_block #{}...", block_doc.number);
-
-    if block_doc.inner_hash.is_none() {
-        fatal_error!(
-            "BlockchainModule : verify_block_hashs() : fatal error : block.inner_hash = None",
-        );
-    }
+    trace!("complete_block #{}...", block_doc.number());
 
     if block_doc.verify_inner_hash() {
         if block_doc.verify_hash() {
-            trace!("Succes to verify_block_hashs #{}", block_doc.number.0);
+            trace!("Succes to verify_block_hashs #{}", block_doc.number().0);
             Ok(())
         } else {
             warn!("BlockchainModule : Refuse Bloc : invalid hash !");
             Err(VerifyBlockHashsError::InvalidHash(
-                block_doc.number,
-                block_doc.hash,
+                block_doc.number(),
+                block_doc.hash(),
             ))
         }
     } else {
diff --git a/lib/modules/blockchain/blockchain/src/dubp/check/mod.rs b/lib/modules/blockchain/blockchain/src/dubp/check/mod.rs
index 0c9959bae305d01dd121f60d7127e2871d1a796e..b14762ea17a0fb7e373689f5b8495bab3d35ec5d 100644
--- a/lib/modules/blockchain/blockchain/src/dubp/check/mod.rs
+++ b/lib/modules/blockchain/blockchain/src/dubp/check/mod.rs
@@ -18,7 +18,7 @@
 pub mod hashs;
 
 use crate::dubp::BlockError;
-use dubp_documents::documents::block::BlockDocument;
+use dubp_documents::documents::block::{BlockDocument, BlockDocumentTrait};
 use dubp_documents::*;
 use dup_crypto::keys::PubKey;
 use durs_blockchain_dal::*;
@@ -39,11 +39,11 @@ pub fn verify_block_validity<W: WebOfTrust>(
     _wot_db: &BinDB<W>,
 ) -> Result<(), BlockError> {
     // Rules that do not concern genesis block
-    if block.number.0 > 0 {
+    if block.number().0 > 0 {
         // Get previous block
         let previous_block_opt = readers::block::get_block_in_local_blockchain(
             blockchain_db,
-            BlockNumber(block.number.0 - 1),
+            BlockNumber(block.number().0 - 1),
         )?;
 
         // Previous block must exist
@@ -53,7 +53,7 @@ pub fn verify_block_validity<W: WebOfTrust>(
         let previous_block = previous_block_opt.expect("safe unwrap");
 
         // Block version must not decrease
-        if previous_block.version > block.version {
+        if previous_block.version() > block.version() {
             return Err(BlockError::InvalidBlock(InvalidBlockError::VersionDecrease));
         }
     }
diff --git a/lib/modules/blockchain/blockchain/src/dubp/mod.rs b/lib/modules/blockchain/blockchain/src/dubp/mod.rs
index 2b2b7feed61a5df6e8e3bdcd80bbc543d65fa364..87a588b54666e5fe1817924b327be1535bc700c2 100644
--- a/lib/modules/blockchain/blockchain/src/dubp/mod.rs
+++ b/lib/modules/blockchain/blockchain/src/dubp/mod.rs
@@ -21,6 +21,7 @@ pub mod check;
 use crate::*;
 use apply::*;
 use check::*;
+use dubp_documents::documents::block::BlockDocumentTrait;
 use dubp_documents::Blockstamp;
 use dubp_documents::Document;
 use durs_blockchain_dal::entities::block::DALBlock;
@@ -71,16 +72,16 @@ pub fn check_and_apply_block(
         &bc.blocks_databases.blockchain_db,
         &bc.forks_dbs,
         block_doc.blockstamp(),
-        block_doc.previous_hash,
+        block_doc.previous_hash(),
     )?;
 
     // Verify block hashs
     dubp::check::hashs::verify_block_hashs(&block_doc)?;
 
     // Check block chainability
-    if (block_doc.number.0 == 0 && bc.current_blockstamp == Blockstamp::default())
-        || (block_doc.number.0 == bc.current_blockstamp.id.0 + 1
-            && unwrap!(block_doc.previous_hash).to_string()
+    if (block_doc.number().0 == 0 && bc.current_blockstamp == Blockstamp::default())
+        || (block_doc.number().0 == bc.current_blockstamp.id.0 + 1
+            && unwrap!(block_doc.previous_hash()).to_string()
                 == bc.current_blockstamp.hash.0.to_string())
     {
         debug!(
@@ -104,7 +105,7 @@ pub fn check_and_apply_block(
         )?;
 
         // If we're in block genesis, get the currency parameters
-        if block_doc.number == BlockNumber(0) {
+        if block_doc.number() == BlockNumber(0) {
             // Open currency_params_db
             let datas_path = durs_conf::get_datas_path(bc.profile_path.clone());
             // Get and write currency params
@@ -124,8 +125,8 @@ pub fn check_and_apply_block(
         )?))
     } else if already_have_block {
         Err(BlockError::AlreadyHaveBlock)
-    } else if block_doc.number.0 >= bc.current_blockstamp.id.0
-        || (bc.current_blockstamp.id.0 - block_doc.number.0)
+    } else if block_doc.number().0 >= bc.current_blockstamp.id.0
+        || (bc.current_blockstamp.id.0 - block_doc.number().0)
             < unwrap!(bc.currency_params).fork_window_size as u32
     {
         debug!(
diff --git a/lib/modules/blockchain/blockchain/src/fork/fork_algo.rs b/lib/modules/blockchain/blockchain/src/fork/fork_algo.rs
index d0d9b1780fcdb3e5f8d6cba2ca1bd1d26c4f861f..2784da53c25de61845252bb67a121538bdc5b311 100644
--- a/lib/modules/blockchain/blockchain/src/fork/fork_algo.rs
+++ b/lib/modules/blockchain/blockchain/src/fork/fork_algo.rs
@@ -13,6 +13,7 @@
 // You should have received a copy of the GNU Affero General Public License
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
+use dubp_documents::documents::block::BlockDocumentTrait;
 use dubp_documents::Blockstamp;
 use durs_blockchain_dal::entities::fork_tree::ForkTree;
 use durs_blockchain_dal::{DALError, ForksDBs};
@@ -33,7 +34,7 @@ pub fn fork_resolution_algo(
         db.get(&current_blockstamp)
             .expect("safe unwrap")
             .block
-            .median_time
+            .common_time()
     })?;
 
     let mut sheets = forks_dbs.fork_tree_db.read(ForkTree::get_sheets)?;
@@ -55,7 +56,7 @@ pub fn fork_resolution_algo(
                 db.get(&branch_head_blockstamp)
                     .expect("safe unwrap")
                     .block
-                    .median_time
+                    .common_time()
             })?;
             if branch_head_blockstamp.id.0 >= current_blockstamp.id.0 + *ADVANCE_BLOCKS
                 && branch_head_median_time >= current_bc_time + *ADVANCE_TIME
@@ -102,7 +103,10 @@ mod tests {
 
         // Generate `FORK_WINDOW_SIZE + 2` mock blocks
         let main_branch: Vec<BlockDocument> =
-            dubp_documents_tests_tools::mocks::gen_empty_timed_blocks(fork_window_size + 2, 0u64);
+            dubp_documents_tests_tools::mocks::gen_empty_timed_blocks_v10(
+                fork_window_size + 2,
+                0u64,
+            );
 
         // Insert mock blocks in forks_dbs
         for block in &main_branch {
@@ -136,17 +140,19 @@ mod tests {
         let fork_point = &main_branch[main_branch.len() - 2];
         let fork_blocks: Vec<BlockDocument> = (0..3)
             .map(|i| {
-                dubp_documents_tests_tools::mocks::gen_empty_timed_block(
-                    Blockstamp {
-                        id: BlockNumber(fork_point.number.0 + i + 1),
-                        hash: BlockHash(dup_crypto_tests_tools::mocks::hash('A')),
-                    },
-                    ADVANCE_TIME - 1,
-                    if i == 0 {
-                        fork_point.hash.expect("safe unwrap").0
-                    } else {
-                        dup_crypto_tests_tools::mocks::hash('A')
-                    },
+                BlockDocument::V10(
+                    dubp_documents_tests_tools::mocks::gen_empty_timed_block_v10(
+                        Blockstamp {
+                            id: BlockNumber(fork_point.number().0 + i + 1),
+                            hash: BlockHash(dup_crypto_tests_tools::mocks::hash('A')),
+                        },
+                        ADVANCE_TIME - 1,
+                        if i == 0 {
+                            fork_point.hash().expect("safe unwrap").0
+                        } else {
+                            dup_crypto_tests_tools::mocks::hash('A')
+                        },
+                    ),
                 )
             })
             .collect();
@@ -173,7 +179,7 @@ mod tests {
 
         // Add the determining fork block
         let determining_blockstamp = Blockstamp {
-            id: BlockNumber(fork_point.number.0 + 4),
+            id: BlockNumber(fork_point.number().0 + 4),
             hash: BlockHash(dup_crypto_tests_tools::mocks::hash('A')),
         };
         assert_eq!(
@@ -181,10 +187,12 @@ mod tests {
             durs_blockchain_dal::writers::block::insert_new_fork_block(
                 &forks_dbs,
                 DALBlock {
-                    block: dubp_documents_tests_tools::mocks::gen_empty_timed_block(
-                        determining_blockstamp,
-                        *ADVANCE_TIME,
-                        dup_crypto_tests_tools::mocks::hash('A'),
+                    block: BlockDocument::V10(
+                        dubp_documents_tests_tools::mocks::gen_empty_timed_block_v10(
+                            determining_blockstamp,
+                            *ADVANCE_TIME,
+                            dup_crypto_tests_tools::mocks::hash('A'),
+                        )
                     ),
                     expire_certs: None,
                 },
@@ -211,17 +219,19 @@ mod tests {
         // The old main branch catches up and overlaps with the fork
         let new_main_blocks: Vec<BlockDocument> = (0..7)
             .map(|i| {
-                dubp_documents_tests_tools::mocks::gen_empty_timed_block(
-                    Blockstamp {
-                        id: BlockNumber(fork_point.number.0 + i + 1),
-                        hash: BlockHash(dup_crypto_tests_tools::mocks::hash('B')),
-                    },
-                    ADVANCE_TIME * 2,
-                    if i == 0 {
-                        fork_point.hash.expect("safe unwrap").0
-                    } else {
-                        dup_crypto_tests_tools::mocks::hash('B')
-                    },
+                BlockDocument::V10(
+                    dubp_documents_tests_tools::mocks::gen_empty_timed_block_v10(
+                        Blockstamp {
+                            id: BlockNumber(fork_point.number().0 + i + 1),
+                            hash: BlockHash(dup_crypto_tests_tools::mocks::hash('B')),
+                        },
+                        ADVANCE_TIME * 2,
+                        if i == 0 {
+                            fork_point.hash().expect("safe unwrap").0
+                        } else {
+                            dup_crypto_tests_tools::mocks::hash('B')
+                        },
+                    ),
                 )
             })
             .collect();
diff --git a/lib/modules/blockchain/blockchain/src/fork/revert_block.rs b/lib/modules/blockchain/blockchain/src/fork/revert_block.rs
index 9966c0baa0bf23154a98268aaa20a5b224f2614c..09e0993517d86c89974363d6f1d32048769eb1d3 100644
--- a/lib/modules/blockchain/blockchain/src/fork/revert_block.rs
+++ b/lib/modules/blockchain/blockchain/src/fork/revert_block.rs
@@ -15,9 +15,10 @@
 
 //! Sub-module that applies a block backwards.
 
-use dubp_documents::documents::block::TxDocOrTxHash;
+use dubp_documents::documents::block::v10::TxDocOrTxHash;
+use dubp_documents::documents::block::{BlockDocument, BlockDocumentTrait, BlockDocumentV10};
 use dubp_documents::documents::transaction::{TxAmount, TxBase};
-use dubp_documents::Document;
+use dubp_documents::{BlockNumber, Document};
 use dup_crypto::keys::*;
 use durs_blockchain_dal::entities::block::DALBlock;
 use durs_blockchain_dal::entities::sources::SourceAmount;
@@ -28,6 +29,7 @@ use durs_common_tools::fatal_error;
 use durs_wot::data::{NewLinkResult, RemLinkResult};
 use durs_wot::{NodeId, WebOfTrust};
 use std::collections::HashMap;
+use unwrap::unwrap;
 
 #[derive(Debug)]
 /// Stores all queries to apply in database to "apply" the block
@@ -52,18 +54,29 @@ impl From<DALError> for RevertValidBlockError {
 }
 
 pub fn revert_block<W: WebOfTrust>(
-    dal_block: &DALBlock,
+    dal_block: DALBlock,
     wot_index: &mut HashMap<PubKey, NodeId>,
     wot_db: &BinDB<W>,
     txs_db: &BinDB<TxV10Datas>,
 ) -> Result<ValidBlockRevertReqs, RevertValidBlockError> {
-    // Revert DALBlock
-    let mut block = dal_block.block.clone();
-    let expire_certs = dal_block
-        .expire_certs
-        .clone()
-        .expect("Try to get expire_certs of an uncompleted block !");
+    match dal_block.block {
+        BlockDocument::V10(block_v10) => revert_block_v10(
+            block_v10,
+            unwrap!(dal_block.expire_certs),
+            wot_index,
+            wot_db,
+            txs_db,
+        ),
+    }
+}
 
+pub fn revert_block_v10<W: WebOfTrust>(
+    mut block: BlockDocumentV10,
+    expire_certs: HashMap<(NodeId, NodeId), BlockNumber>,
+    wot_index: &mut HashMap<PubKey, NodeId>,
+    wot_db: &BinDB<W>,
+    txs_db: &BinDB<TxV10Datas>,
+) -> Result<ValidBlockRevertReqs, RevertValidBlockError> {
     // Get transactions
     let dal_txs: Vec<DALTxV10> = block
         .transactions
@@ -81,7 +94,7 @@ pub fn revert_block<W: WebOfTrust>(
         .collect();
 
     // Revert reduce block
-    block.compute_inner_hash();
+    block.generate_inner_hash();
     debug!(
         "BlockchainModule : revert_valid_block({})",
         block.blockstamp()
@@ -116,10 +129,10 @@ pub fn revert_block<W: WebOfTrust>(
     let mut wot_dbs_requests = Vec::new();
     // Revert expire_certs
     if !expire_certs.is_empty() {
-        for ((source, target), created_block_id) in expire_certs {
+        for ((source, target), created_block_id) in &expire_certs {
             wot_db
                 .write(|db| {
-                    let result = db.add_link(source, target);
+                    let result = db.add_link(*source, *target);
                     match result {
                         NewLinkResult::Ok(_) => {}
                         _ => fatal_error!(
@@ -132,9 +145,9 @@ pub fn revert_block<W: WebOfTrust>(
                 })
                 .expect("Fail to write in WotDB");
             wot_dbs_requests.push(WotsDBsWriteQuery::RevertExpireCert(
-                source,
-                target,
-                created_block_id,
+                *source,
+                *target,
+                *created_block_id,
             ));
         }
     }
@@ -247,14 +260,17 @@ pub fn revert_block<W: WebOfTrust>(
             wot_dbs_requests.push(WotsDBsWriteQuery::RevertRenewalIdentity(
                 joiner.issuers()[0],
                 wot_id,
-                block.median_time,
+                block.common_time(),
                 joiner.blockstamp().id,
             ));
         }
     }
     // Return DBs requests
     Ok(ValidBlockRevertReqs(
-        BlocksDBsWriteQuery::RevertBlock(dal_block.clone()),
+        BlocksDBsWriteQuery::RevertBlock(DALBlock {
+            block: BlockDocument::V10(block),
+            expire_certs: Some(expire_certs),
+        }),
         wot_dbs_requests,
         currency_dbs_requests,
     ))
diff --git a/lib/modules/blockchain/blockchain/src/fork/rollback.rs b/lib/modules/blockchain/blockchain/src/fork/rollback.rs
index fa060ea3c94c9851fdecfe458b88f508119046f4..df2f602f21bbbbd819b219f98817ab97a02d36cd 100644
--- a/lib/modules/blockchain/blockchain/src/fork/rollback.rs
+++ b/lib/modules/blockchain/blockchain/src/fork/rollback.rs
@@ -37,9 +37,10 @@ pub fn apply_rollback(bc: &mut BlockchainModule, new_bc_branch: Vec<Blockstamp>)
                 fatal_error!("revert block {} fail !", bc.current_blockstamp);
             })
         {
+            let blockstamp = dal_block.block.blockstamp();
             let ValidBlockRevertReqs(bc_db_query, wot_dbs_queries, tx_dbs_queries) =
                 super::revert_block::revert_block(
-                    &dal_block,
+                    dal_block,
                     &mut bc.wot_index,
                     &bc.wot_databases.wot_db,
                     &bc.currency_databases.tx_db,
@@ -47,7 +48,6 @@ pub fn apply_rollback(bc: &mut BlockchainModule, new_bc_branch: Vec<Blockstamp>)
                 .unwrap_or_else(|_| {
                     fatal_error!("revert block {} fail !", bc.current_blockstamp);
                 });
-            let blockstamp = dal_block.block.blockstamp();
             // Apply db requests
             bc_db_query
                 .apply(
diff --git a/lib/modules/blockchain/blockchain/src/fork/stackable_blocks.rs b/lib/modules/blockchain/blockchain/src/fork/stackable_blocks.rs
index f6aeaf8a8fb1f3908ec0ecb4926494a505781800..905d059dabf4dd94b4163f9590dd746aebdc400a 100644
--- a/lib/modules/blockchain/blockchain/src/fork/stackable_blocks.rs
+++ b/lib/modules/blockchain/blockchain/src/fork/stackable_blocks.rs
@@ -16,6 +16,7 @@
 //! Sub-module that finds and applies the orphaned blocks that have become stackable on the local blockchain.
 
 use crate::*;
+use dubp_documents::documents::block::BlockDocumentTrait;
 use unwrap::unwrap;
 
 pub fn apply_stackable_blocks(bc: &mut BlockchainModule) {
@@ -29,9 +30,9 @@ pub fn apply_stackable_blocks(bc: &mut BlockchainModule) {
             break 'blockchain;
         } else {
             for stackable_block in stackable_blocks {
-                debug!("stackable_block({})", stackable_block.block.number);
+                debug!("stackable_block({})", stackable_block.block.number());
 
-                let stackable_block_number = stackable_block.block.number;
+                let stackable_block_number = stackable_block.block.number();
                 let stackable_block_blockstamp = stackable_block.block.blockstamp();
 
                 if let Ok(CheckAndApplyBlockReturn::ValidMainBlock(ValidBlockApplyReqs(
diff --git a/lib/modules/blockchain/blockchain/src/sync/download/json_reader_worker.rs b/lib/modules/blockchain/blockchain/src/sync/download/json_reader_worker.rs
index 6e2dac28d08c179a305a1451f78b008a04a129a6..1c038957f4ddabe441c90d1a11d3deda29ee5734 100644
--- a/lib/modules/blockchain/blockchain/src/sync/download/json_reader_worker.rs
+++ b/lib/modules/blockchain/blockchain/src/sync/download/json_reader_worker.rs
@@ -87,7 +87,7 @@ pub fn json_reader_worker(
         // Send TargetBlockcstamp
         sender_sync_thread
             .send(MessForSyncThread::Target(
-                last_block.currency.clone(),
+                last_block.currency().into(),
                 last_block.blockstamp(),
             ))
             .expect("Fatal error : sync_thread unrechable !");
diff --git a/lib/modules/blockchain/blockchain/src/sync/mod.rs b/lib/modules/blockchain/blockchain/src/sync/mod.rs
index 5986d6f1cadeacb7c367810425e7160fd809ae0d..7c9b07bd3c08db4e0f127bc03057316de05bfc40 100644
--- a/lib/modules/blockchain/blockchain/src/sync/mod.rs
+++ b/lib/modules/blockchain/blockchain/src/sync/mod.rs
@@ -18,6 +18,7 @@ mod download;
 
 use crate::dubp::apply::apply_valid_block;
 use crate::*;
+use dubp_documents::documents::block::BlockDocumentTrait;
 use dubp_documents::{BlockHash, BlockNumber};
 use dup_crypto::keys::*;
 use dup_currency_params::{CurrencyName, CurrencyParameters};
@@ -251,7 +252,7 @@ pub fn local_sync<DC: DursConfTrait>(profile_path: PathBuf, conf: &DC, sync_opts
         // Get and write currency params
         if !get_currency_params {
             let datas_path = durs_conf::get_datas_path(profile_path.clone());
-            if block_doc.number == BlockNumber(0) {
+            if block_doc.number() == BlockNumber(0) {
                 currency_params = Some(
                     durs_blockchain_dal::readers::currency_params::get_and_write_currency_params(
                         &datas_path,
@@ -270,11 +271,11 @@ pub fn local_sync<DC: DursConfTrait>(profile_path: PathBuf, conf: &DC, sync_opts
         let currency_params = unwrap!(currency_params);
 
         // Push block median_time in blocks_not_expiring
-        blocks_not_expiring.push_back(block_doc.median_time);
+        blocks_not_expiring.push_back(block_doc.common_time());
         // Get blocks_expiring
         let mut blocks_expiring = Vec::new();
         while blocks_not_expiring.front().copied()
-            < Some(block_doc.median_time - currency_params.sig_validity)
+            < Some(block_doc.common_time() - currency_params.sig_validity)
         {
             last_block_expiring += 1;
             blocks_expiring.push(BlockNumber(last_block_expiring as u32));
diff --git a/lib/modules/ws2p-v1-legacy/src/lib.rs b/lib/modules/ws2p-v1-legacy/src/lib.rs
index 45c14d5181caef7de4120d3ddaaad1f90cb7878b..d2ee5314c93ca5a6b4c1afcf1076057efff582b8 100644
--- a/lib/modules/ws2p-v1-legacy/src/lib.rs
+++ b/lib/modules/ws2p-v1-legacy/src/lib.rs
@@ -878,7 +878,7 @@ mod tests {
     use super::*;
     use crate::ws_connections::requests::sent::network_request_to_json;
     use crate::ws_connections::requests::*;
-    use dubp_documents::documents::block::BlockDocument;
+    use dubp_documents::documents::block::{BlockDocument, BlockDocumentTrait};
     use dubp_documents::parsers::blocks::parse_json_block_from_serde_value;
     use dubp_documents::BlockNumber;
 
@@ -1028,19 +1028,19 @@ mod tests {
                 }
             ],
         });
-        let mut block: BlockDocument = parse_json_block_from_serde_value(&json_block)
+        let block: BlockDocument = parse_json_block_from_serde_value(&json_block)
             .expect("Fail to parse test json block !");
         assert_eq!(
             block
-                .inner_hash
+                .inner_hash()
                 .expect("Try to get inner_hash of an uncompleted or reduce block !")
                 .to_hex(),
             "61F02B1A6AE2E4B9A1FD66CE673258B4B21C0076795571EE3C9DC440DD06C46C"
         );
-        block.compute_hash();
+        //block.generate_hash();
         assert_eq!(
             block
-                .hash
+                .hash()
                 .expect("Try to get hash of an uncompleted or reduce block !")
                 .0
                 .to_hex(),
diff --git a/lib/modules/ws2p-v1-legacy/src/serializers/block.rs b/lib/modules/ws2p-v1-legacy/src/serializers/block.rs
index a896d954ce458443f614882a1f609f3b1d45201a..95c8afe927b153faab8043127544dec28ce375a8 100644
--- a/lib/modules/ws2p-v1-legacy/src/serializers/block.rs
+++ b/lib/modules/ws2p-v1-legacy/src/serializers/block.rs
@@ -16,9 +16,17 @@
 //! Sub-module that serialize BlockDocument into WS2Pv1 json format
 
 use super::IntoWS2Pv1Json;
-use dubp_documents::documents::block::BlockDocumentStringified;
+use dubp_documents::documents::block::{BlockDocumentStringified, BlockDocumentV10Stringified};
 
 impl IntoWS2Pv1Json for BlockDocumentStringified {
+    fn into_ws2p_v1_json(self) -> serde_json::Value {
+        match self {
+            BlockDocumentStringified::V10(block_str_v10) => block_str_v10.into_ws2p_v1_json(),
+        }
+    }
+}
+
+impl IntoWS2Pv1Json for BlockDocumentV10Stringified {
     fn into_ws2p_v1_json(self) -> serde_json::Value {
         let actives = self
             .actives
diff --git a/lib/tests-tools/documents-tests-tools/src/mocks/mod.rs b/lib/tests-tools/documents-tests-tools/src/mocks/mod.rs
index f00c42fecea02158cda0d8b272beec5ea2f97acd..18a189aee25a12bc3d823c80475b76091a7ea01c 100644
--- a/lib/tests-tools/documents-tests-tools/src/mocks/mod.rs
+++ b/lib/tests-tools/documents-tests-tools/src/mocks/mod.rs
@@ -17,7 +17,7 @@
 
 pub mod identity;
 
-use dubp_documents::documents::block::BlockDocument;
+use dubp_documents::documents::block::{BlockDocument, BlockDocumentV10};
 use dubp_documents::*;
 use dup_crypto::hashs::Hash;
 use dup_currency_params::CurrencyName;
@@ -35,10 +35,10 @@ pub fn generate_blockstamps(n: usize) -> Vec<Blockstamp> {
 }
 
 /// Generate n empty timed block document
-pub fn gen_empty_timed_blocks(n: usize, time_step: u64) -> Vec<BlockDocument> {
+pub fn gen_empty_timed_blocks_v10(n: usize, time_step: u64) -> Vec<BlockDocument> {
     (0..n)
         .map(|i| {
-            gen_empty_timed_block(
+            BlockDocument::V10(gen_empty_timed_block_v10(
                 Blockstamp {
                     id: BlockNumber(i as u32),
                     hash: BlockHash(dup_crypto_tests_tools::mocks::hash_from_byte(
@@ -51,19 +51,19 @@ pub fn gen_empty_timed_blocks(n: usize, time_step: u64) -> Vec<BlockDocument> {
                 } else {
                     dup_crypto_tests_tools::mocks::hash_from_byte(((i - 1) % 255) as u8)
                 },
-            )
+            ))
         })
         .collect()
 }
 
 /// Generate empty timed block document
 /// (usefull for tests that only need blockstamp and median_time fields)
-pub fn gen_empty_timed_block(
+pub fn gen_empty_timed_block_v10(
     blockstamp: Blockstamp,
     time: u64,
     previous_hash: Hash,
-) -> BlockDocument {
-    BlockDocument {
+) -> BlockDocumentV10 {
+    BlockDocumentV10 {
         version: 10,
         nonce: 0,
         number: blockstamp.id,
@@ -93,6 +93,5 @@ pub fn gen_empty_timed_block(
         certifications: vec![],
         transactions: vec![],
         inner_hash: None,
-        inner_hash_and_nonce_str: "".to_owned(),
     }
 }
diff --git a/lib/tools/currency-params/src/lib.rs b/lib/tools/currency-params/src/lib.rs
index e566fdc7acba11b22fcb4e470cf3b32e7064c620..fd20b2e6b27b8f686a1604f5754908b1d36fe83b 100644
--- a/lib/tools/currency-params/src/lib.rs
+++ b/lib/tools/currency-params/src/lib.rs
@@ -46,6 +46,12 @@ impl Display for CurrencyName {
     }
 }
 
+impl From<&str> for CurrencyName {
+    fn from(s: &str) -> Self {
+        CurrencyName(s.to_owned())
+    }
+}
+
 #[derive(Debug, Copy, Clone)]
 /// Currency parameters
 pub struct CurrencyParameters {
diff --git a/lib/tools/documents/src/documents/block.rs b/lib/tools/documents/src/documents/block.rs
index ebac6bcb578cbafc7a6c134d1d73515313bdc16f..f9ded4b747a4a46d9f4106c9f2e1465f8f3c6ec5 100644
--- a/lib/tools/documents/src/documents/block.rs
+++ b/lib/tools/documents/src/documents/block.rs
@@ -1,4 +1,4 @@
-//  Copyright (C) 2018  The Duniter Project Developers.
+//  Copyright (C) 2018  The Durs Project Developers.
 //
 // This program is free software: you can redistribute it and/or modify
 // it under the terms of the GNU Affero General Public License as
@@ -15,922 +15,236 @@
 
 //! Wrappers around Block document.
 
-use dup_crypto::hashs::Hash;
-use dup_crypto::keys::*;
-use dup_currency_params::genesis_block_params::v10::BlockV10Parameters;
-use dup_currency_params::CurrencyName;
-use durs_common_tools::fatal_error;
-use std::ops::Deref;
-use unwrap::unwrap;
+pub mod v10;
 
-use crate::blockstamp::Blockstamp;
-use crate::documents::certification::CertificationDocument;
-use crate::documents::identity::IdentityDocument;
-use crate::documents::membership::MembershipDocument;
-use crate::documents::revocation::RevocationDocument;
-use crate::documents::transaction::TransactionDocument;
-use crate::documents::*;
-use crate::text_document_traits::*;
+pub use v10::{BlockDocumentV10, BlockDocumentV10Stringified};
 
-/// Store a transaction document or just its hash.
-#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
-pub enum TxDocOrTxHash {
-    /// Transaction document
-    TxDoc(Box<TransactionDocument>),
-    /// transaction hash
-    TxHash(Hash),
-}
-
-impl TxDocOrTxHash {
-    /// Lightens the TxDocOrTxHash (for example to store it while minimizing the space required)
-    /// lightening consists in transforming the document by its hash.
-    pub fn reduce(&self) -> TxDocOrTxHash {
-        if let TxDocOrTxHash::TxDoc(ref tx_doc) = self {
-            let tx_doc = tx_doc.deref();
-            if let Some(ref hash) = tx_doc.get_hash_opt() {
-                TxDocOrTxHash::TxHash(*hash)
-            } else {
-                TxDocOrTxHash::TxHash(tx_doc.clone().compute_hash())
-            }
-        } else {
-            self.clone()
-        }
-    }
-    /// Get TxDoc variant
-    pub fn unwrap_doc(&self) -> TransactionDocument {
-        if let TxDocOrTxHash::TxDoc(ref tx_doc) = self {
-            tx_doc.deref().clone()
-        } else {
-            fatal_error!("Try to unwrap_doc() in a TxHash() variant of TxDocOrTxHash !")
-        }
-    }
-}
+use crate::blockstamp::Blockstamp;
+use crate::{BlockHash, BlockNumber, Document, ToStringObject};
+use dup_crypto::hashs::Hash;
+use dup_crypto::keys::{PrivKey, PubKey, PublicKey};
 
 /// Wrap a Block document.
 ///
 /// Must be created by parsing a text document or using a builder.
 #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
-pub struct BlockDocument {
-    /// Version
-    pub version: u32,
-    /// Nonce
-    pub nonce: u64,
-    /// number
-    pub number: BlockNumber,
-    /// Minimal proof of work difficulty
-    pub pow_min: usize,
-    /// Local time of the block issuer
-    pub time: u64,
-    /// Average time
-    pub median_time: u64,
-    /// Members count
-    pub members_count: usize,
-    /// Monetary mass
-    pub monetary_mass: usize,
-    /// Unit base (power of ten)
-    pub unit_base: usize,
-    /// Number of compute members in the current frame
-    pub issuers_count: usize,
-    /// Current frame size (in blocks)
-    pub issuers_frame: isize,
-    /// Current frame variation buffer
-    pub issuers_frame_var: isize,
-    /// Currency.
-    pub currency: CurrencyName,
-    /// Document issuer (there should be only one).
-    pub issuers: Vec<PubKey>,
-    /// Document signature (there should be only one).
-    /// This vector is empty, when the block is generated but the proof of work has not yet started
-    pub signatures: Vec<Sig>,
-    /// The hash is None, when the block is generated but the proof of work has not yet started
-    pub hash: Option<BlockHash>,
-    /// Currency parameters (only in genesis block)
-    pub parameters: Option<BlockV10Parameters>,
-    /// Hash of the previous block
-    pub previous_hash: Option<Hash>,
-    /// Issuer of the previous block
-    pub previous_issuer: Option<PubKey>,
-    /// Hash of the deterministic content of the block
-    pub inner_hash: Option<Hash>,
-    /// Amount of new dividend created at this block, None if no dividend is created at this block
-    pub dividend: Option<usize>,
-    /// Identities
-    pub identities: Vec<IdentityDocument>,
-    /// joiners
-    pub joiners: Vec<MembershipDocument>,
-    /// Actives (=renewals)
-    pub actives: Vec<MembershipDocument>,
-    /// Leavers
-    pub leavers: Vec<MembershipDocument>,
-    /// Revokeds
-    pub revoked: Vec<TextDocumentFormat<RevocationDocument>>,
-    /// Excludeds
-    pub excluded: Vec<PubKey>,
-    /// Certifications
-    pub certifications: Vec<TextDocumentFormat<CertificationDocument>>,
-    /// Transactions
-    pub transactions: Vec<TxDocOrTxHash>,
-    /// Part to sign
-    pub inner_hash_and_nonce_str: String,
+pub enum BlockDocument {
+    V10(BlockDocumentV10),
 }
 
-impl BlockDocument {
-    /// Return previous blockstamp
-    pub fn previous_blockstamp(&self) -> Blockstamp {
-        if self.number.0 > 0 {
-            Blockstamp {
-                id: BlockNumber(self.number.0 - 1),
-                hash: BlockHash(unwrap!(self.previous_hash)),
-            }
-        } else {
-            Blockstamp::default()
-        }
-    }
-    /// Compute inner hash
-    pub fn compute_inner_hash(&mut self) {
-        self.inner_hash = Some(Hash::compute_str(&self.generate_compact_inner_text()));
-    }
+pub trait BlockDocumentTrait {
+    /// Common time in block (also known as 'blockchain time')
+    fn common_time(&self) -> u64;
+    /// Compute hash
+    fn compute_hash(&self) -> BlockHash;
     /// Compute inner hash
-    pub fn verify_inner_hash(&self) -> bool {
-        match self.inner_hash {
-            Some(inner_hash) => {
-                inner_hash == Hash::compute_str(&self.generate_compact_inner_text())
-            }
-            None => false,
-        }
-    }
-    // Generate the character string that will be hashed
-    fn generate_will_hashed_string(&self) -> String {
-        format!(
-            "InnerHash: {}\nNonce: {}\n",
-            self.inner_hash
-                .expect("Try to get inner_hash of an uncompleted or reduce block !")
-                .to_hex(),
-            self.nonce
-        )
-    }
+    fn compute_inner_hash(&self) -> Hash {
+        Hash::compute_str(&self.generate_compact_inner_text())
+    }
+    /// Compute the character string that will be hashed
+    fn compute_will_hashed_string(&self) -> String;
+    /// Compute the character string that will be signed
+    fn compute_will_signed_string(&self) -> String;
+    /// Get current frame size (in blocks)
+    fn current_frame_size(&self) -> usize;
+    /// Generate compact inner text (for compute inner_hash)
+    fn generate_compact_inner_text(&self) -> String;
+    /// Compute hash and save it in document
+    fn generate_hash(&mut self);
+    /// Compute inner hash and save it in document
+    fn generate_inner_hash(&mut self);
+    /// Get block hash
+    fn hash(&self) -> Option<BlockHash>;
+    /// Increment nonce
+    fn increment_nonce(&mut self);
+    /// Get block inner hash
+    fn inner_hash(&self) -> Option<Hash>;
+    /// Get number of compute members in the current frame
+    fn issuers_count(&self) -> usize;
+    /// Get block number
+    fn number(&self) -> BlockNumber;
+    /// Get previous hash
+    fn previous_hash(&self) -> Option<Hash>;
+    /// Get previous blockstamp
+    fn previous_blockstamp(&self) -> Blockstamp;
+    /// Lightens the block (for example to store it while minimizing the space required)
+    fn reduce(&mut self);
+    /// Verify inner hash
+    fn verify_inner_hash(&self) -> bool;
     /// Verify block hash
-    pub fn verify_hash(&self) -> bool {
-        match self.hash {
-            Some(hash) => {
-                let datas = format!(
-                    "{}{}\n",
-                    self.generate_will_hashed_string(),
-                    self.signatures[0]
-                );
-                let expected_hash = BlockHash(Hash::compute_str(&datas));
-                if hash == expected_hash {
-                    true
-                } else {
-                    warn!(
-                        "Block #{} have invalid hash (expected='{}', actual='{}', datas='{}').",
-                        self.number.0, expected_hash, hash, datas
-                    );
-                    false
-                }
-            }
-            None => false,
+    fn verify_hash(&self) -> bool;
+    /// Sign block
+    fn sign(&mut self, privkey: PrivKey);
+}
+
+impl BlockDocumentTrait for BlockDocument {
+    #[inline]
+    fn compute_hash(&self) -> BlockHash {
+        match self {
+            BlockDocument::V10(block) => block.compute_hash(),
         }
     }
-    /// Fill inner_hash_and_nonce_str
-    pub fn fill_inner_hash_and_nonce_str(&mut self, new_nonce: Option<u64>) {
-        if let Some(new_nonce) = new_nonce {
-            self.nonce = new_nonce;
+    #[inline]
+    fn compute_will_hashed_string(&self) -> String {
+        match self {
+            BlockDocument::V10(block) => block.compute_will_hashed_string(),
         }
-        self.inner_hash_and_nonce_str = self.generate_will_hashed_string();
-    }
-    /// Sign block
-    pub fn sign(&mut self, privkey: PrivKey) {
-        self.fill_inner_hash_and_nonce_str(None);
-        self.signatures = vec![privkey.sign(self.inner_hash_and_nonce_str.as_bytes())];
-    }
-    /// Compute hash
-    pub fn compute_hash(&mut self) {
-        self.hash = Some(BlockHash(Hash::compute_str(&format!(
-            "{}{}\n",
-            self.generate_will_hashed_string(),
-            self.signatures[0]
-        ))));
     }
-    /// Lightens the block (for example to store it while minimizing the space required)
-    pub fn reduce(&mut self) {
-        //self.hash = None;
-        self.inner_hash = None;
-        self.inner_hash_and_nonce_str = String::with_capacity(0);
-        for i in &mut self.identities {
-            i.reduce();
-        }
-        for i in &mut self.joiners {
-            i.reduce();
+    #[inline]
+    fn compute_will_signed_string(&self) -> String {
+        match self {
+            BlockDocument::V10(block) => block.compute_will_signed_string(),
         }
-        for i in &mut self.actives {
-            i.reduce();
+    }
+    #[inline]
+    fn current_frame_size(&self) -> usize {
+        match self {
+            BlockDocument::V10(block) => block.current_frame_size(),
         }
-        for i in &mut self.leavers {
-            i.reduce();
+    }
+    #[inline]
+    fn generate_compact_inner_text(&self) -> String {
+        match self {
+            BlockDocument::V10(block) => block.generate_compact_inner_text(),
         }
-        for i in &mut self.transactions {
-            i.reduce();
+    }
+    #[inline]
+    fn generate_hash(&mut self) {
+        match self {
+            BlockDocument::V10(block) => block.generate_hash(),
         }
     }
-    /// 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");
-            identities_str.push_str(&identity.generate_compact_text());
+    #[inline]
+    fn generate_inner_hash(&mut self) {
+        match self {
+            BlockDocument::V10(block) => block.generate_inner_hash(),
         }
-        let mut joiners_str = String::from("");
-        for joiner in self.joiners.clone() {
-            joiners_str.push_str("\n");
-            joiners_str.push_str(&joiner.generate_compact_text());
+    }
+    #[inline]
+    fn hash(&self) -> Option<BlockHash> {
+        match self {
+            BlockDocument::V10(block) => block.hash(),
         }
-        let mut actives_str = String::from("");
-        for active in self.actives.clone() {
-            actives_str.push_str("\n");
-            actives_str.push_str(&active.generate_compact_text());
+    }
+    #[inline]
+    fn increment_nonce(&mut self) {
+        match self {
+            BlockDocument::V10(block) => block.increment_nonce(),
         }
-        let mut leavers_str = String::from("");
-        for leaver in self.leavers.clone() {
-            leavers_str.push_str("\n");
-            leavers_str.push_str(&leaver.generate_compact_text());
+    }
+    #[inline]
+    fn inner_hash(&self) -> Option<Hash> {
+        match self {
+            BlockDocument::V10(block) => block.inner_hash(),
         }
-        let mut identities_str = String::from("");
-        for identity in self.identities.clone() {
-            identities_str.push_str("\n");
-            identities_str.push_str(&identity.generate_compact_text());
+    }
+    #[inline]
+    fn issuers_count(&self) -> usize {
+        match self {
+            BlockDocument::V10(block) => block.issuers_count(),
         }
-        let mut revokeds_str = String::from("");
-        for revocation in self.revoked.clone() {
-            revokeds_str.push_str("\n");
-            revokeds_str.push_str(&revocation.as_compact_text());
+    }
+    #[inline]
+    fn common_time(&self) -> u64 {
+        match self {
+            BlockDocument::V10(block) => block.common_time(),
         }
-        let mut excludeds_str = String::from("");
-        for exclusion in self.excluded.clone() {
-            excludeds_str.push_str("\n");
-            excludeds_str.push_str(&exclusion.to_string());
+    }
+    #[inline]
+    fn number(&self) -> BlockNumber {
+        match self {
+            BlockDocument::V10(block) => block.number(),
         }
-        let mut certifications_str = String::from("");
-        for certification in self.certifications.clone() {
-            certifications_str.push_str("\n");
-            certifications_str.push_str(&certification.as_compact_text());
+    }
+    #[inline]
+    fn previous_blockstamp(&self) -> Blockstamp {
+        match self {
+            BlockDocument::V10(block) => block.previous_blockstamp(),
         }
-        let mut transactions_str = String::from("");
-        for transaction in self.transactions.clone() {
-            if let TxDocOrTxHash::TxDoc(transaction) = transaction {
-                transactions_str.push_str("\n");
-                transactions_str.push_str(&transaction.deref().generate_compact_text());
-            }
+    }
+    #[inline]
+    fn previous_hash(&self) -> Option<Hash> {
+        match self {
+            BlockDocument::V10(block) => block.previous_hash(),
         }
-        let mut dividend_str = String::from("");
-        if let Some(dividend) = self.dividend {
-            if dividend > 0 {
-                dividend_str.push_str("UniversalDividend: ");
-                dividend_str.push_str(&dividend.to_string());
-                dividend_str.push_str("\n");
-            }
+    }
+    #[inline]
+    fn reduce(&mut self) {
+        match self {
+            BlockDocument::V10(block) => block.reduce(),
         }
-        let mut parameters_str = String::from("");
-        if let Some(params) = self.parameters {
-            parameters_str.push_str("Parameters: ");
-            parameters_str.push_str(&params.to_string());
-            parameters_str.push_str("\n");
+    }
+    #[inline]
+    fn verify_inner_hash(&self) -> bool {
+        match self {
+            BlockDocument::V10(block) => block.verify_inner_hash(),
         }
-        let mut previous_hash_str = String::from("");
-        if self.number.0 > 0 {
-            previous_hash_str.push_str("PreviousHash: ");
-            previous_hash_str.push_str(&unwrap!(self.previous_hash).to_string());
-            previous_hash_str.push_str("\n");
+    }
+    #[inline]
+    fn verify_hash(&self) -> bool {
+        match self {
+            BlockDocument::V10(block) => block.verify_hash(),
         }
-        let mut previous_issuer_str = String::from("");
-        if self.number.0 > 0 {
-            previous_issuer_str.push_str("PreviousIssuer: ");
-            previous_issuer_str.push_str(
-                &self
-                    .previous_issuer
-                    .expect("No genesis block must have previous issuer")
-                    .to_string(),
-            );
-            previous_issuer_str.push_str("\n");
+    }
+    #[inline]
+    fn sign(&mut self, privkey: PrivKey) {
+        match self {
+            BlockDocument::V10(block) => block.sign(privkey),
         }
-        format!(
-            "Version: {version}
-Type: Block
-Currency: {currency}
-Number: {block_number}
-PoWMin: {pow_min}
-Time: {time}
-MedianTime: {median_time}
-{dividend}UnitBase: {unit_base}
-Issuer: {issuer}
-IssuersFrame: {issuers_frame}
-IssuersFrameVar: {issuers_frame_var}
-DifferentIssuersCount: {issuers_count}
-{parameters}{previous_hash}{previous_issuer}MembersCount: {members_count}
-Identities:{identities}
-Joiners:{joiners}
-Actives:{actives}
-Leavers:{leavers}
-Revoked:{revoked}
-Excluded:{excluded}
-Certifications:{certifications}
-Transactions:{transactions}
-",
-            version = self.version,
-            currency = self.currency,
-            block_number = self.number,
-            pow_min = self.pow_min,
-            time = self.time,
-            median_time = self.median_time,
-            dividend = dividend_str,
-            unit_base = self.unit_base,
-            issuer = self.issuers[0],
-            issuers_frame = self.issuers_frame,
-            issuers_frame_var = self.issuers_frame_var,
-            issuers_count = self.issuers_count,
-            parameters = parameters_str,
-            previous_hash = previous_hash_str,
-            previous_issuer = previous_issuer_str,
-            members_count = self.members_count,
-            identities = identities_str,
-            joiners = joiners_str,
-            actives = actives_str,
-            leavers = leavers_str,
-            revoked = revokeds_str,
-            excluded = excludeds_str,
-            certifications = certifications_str,
-            transactions = transactions_str,
-        )
     }
 }
 
 impl Document for BlockDocument {
     type PublicKey = PubKey;
-    type CurrencyType = str;
 
     fn version(&self) -> u16 {
-        10
+        match self {
+            BlockDocument::V10(_) => 10u16,
+        }
     }
 
     fn currency(&self) -> &str {
-        &self.currency.0
+        match self {
+            BlockDocument::V10(block) => block.currency(),
+        }
     }
 
     fn blockstamp(&self) -> Blockstamp {
-        Blockstamp {
-            id: self.number,
-            hash: self
-                .hash
-                .expect("Fatal error : try to get blockstamp of an uncomplete or reduce block !"),
+        match self {
+            BlockDocument::V10(block) => block.blockstamp(),
         }
     }
 
-    fn issuers(&self) -> &Vec<PubKey> {
-        &self.issuers
+    fn issuers(&self) -> &Vec<Self::PublicKey> {
+        match self {
+            BlockDocument::V10(block) => block.issuers(),
+        }
     }
 
-    fn signatures(&self) -> &Vec<Sig> {
-        &self.signatures
+    fn signatures(&self) -> &Vec<<Self::PublicKey as PublicKey>::Signature> {
+        match self {
+            BlockDocument::V10(block) => block.signatures(),
+        }
     }
 
     fn as_bytes(&self) -> &[u8] {
-        self.inner_hash_and_nonce_str.as_bytes()
-    }
-}
-
-impl CompactTextDocument for BlockDocument {
-    fn as_compact_text(&self) -> String {
-        let compact_inner_text = self.generate_compact_inner_text();
-        format!(
-            "{}InnerHash: {}\nNonce: ",
-            compact_inner_text,
-            self.inner_hash
-                .expect("Try to get inner_hash of an uncompleted or reduce block !")
-                .to_hex()
-        )
-    }
-}
-
-impl TextDocument for BlockDocument {
-    type CompactTextDocument_ = BlockDocument;
-
-    fn as_text(&self) -> &str {
-        fatal_error!(
-            "Dev error: function not implemented. Please use to_compact_document() instead"
-        );
-    }
-
-    fn to_compact_document(&self) -> Self::CompactTextDocument_ {
-        self.clone()
-    }
-}
-
-impl IntoSpecializedDocument<DUBPDocument> for BlockDocument {
-    fn into_specialized(self) -> DUBPDocument {
-        DUBPDocument::Block(Box::new(self))
+        match self {
+            BlockDocument::V10(block) => block.as_bytes(),
+        }
     }
 }
 
 #[derive(Clone, Debug, Deserialize, Serialize)]
-pub struct BlockDocumentStringified {
-    /// Version
-    pub version: u64,
-    /// Nonce
-    pub nonce: u64,
-    /// number
-    pub number: u64,
-    /// Minimal proof of work difficulty
-    pub pow_min: u64,
-    /// Local time of the block issuer
-    pub time: u64,
-    /// Average time
-    pub median_time: u64,
-    /// Members count
-    pub members_count: u64,
-    /// Monetary mass
-    pub monetary_mass: u64,
-    /// Unit base (power of ten)
-    pub unit_base: u64,
-    /// Number of compute members in the current frame
-    pub issuers_count: u64,
-    /// Current frame size (in blocks)
-    pub issuers_frame: i64,
-    /// Current frame variation buffer
-    pub issuers_frame_var: i64,
-    /// Currency.
-    pub currency: String,
-    /// Document issuer (there should be only one).
-    pub issuers: Vec<String>,
-    /// Document signature (there should be only one).
-    /// This vector is empty, when the block is generated but the proof of work has not yet started
-    pub signatures: Vec<String>,
-    /// The hash is None, when the block is generated but the proof of work has not yet started
-    pub hash: Option<String>,
-    /// Currency parameters (only in genesis block)
-    pub parameters: Option<String>,
-    /// Hash of the previous block
-    pub previous_hash: Option<String>,
-    /// Issuer of the previous block
-    pub previous_issuer: Option<String>,
-    /// Hash of the deterministic content of the block
-    pub inner_hash: Option<String>,
-    /// Amount of new dividend created at this block, None if no dividend is created at this block
-    pub dividend: Option<u64>,
-    /// Identities
-    pub identities: Vec<IdentityStringDocument>,
-    /// joiners
-    pub joiners: Vec<MembershipStringDocument>,
-    /// Actives (=renewals)
-    pub actives: Vec<MembershipStringDocument>,
-    /// Leavers
-    pub leavers: Vec<MembershipStringDocument>,
-    /// Revokeds
-    pub revoked: Vec<CompactRevocationStringDocument>,
-    /// Excludeds
-    pub excluded: Vec<String>,
-    /// Certifications
-    pub certifications: Vec<CompactCertificationStringDocument>,
-    /// Transactions
-    pub transactions: Vec<TransactionDocumentStringified>,
+pub enum BlockDocumentStringified {
+    V10(BlockDocumentV10Stringified),
 }
 
 impl ToStringObject for BlockDocument {
     type StringObject = BlockDocumentStringified;
-    /// Transforms an object into a json object
-    fn to_string_object(&self) -> BlockDocumentStringified {
-        BlockDocumentStringified {
-            version: u64::from(self.version),
-            nonce: self.nonce,
-            number: u64::from(self.number.0),
-            pow_min: self.pow_min as u64,
-            time: self.time,
-            median_time: self.median_time,
-            members_count: self.members_count as u64,
-            monetary_mass: self.monetary_mass as u64,
-            unit_base: self.unit_base as u64,
-            issuers_count: self.issuers_count as u64,
-            issuers_frame: self.issuers_frame as i64,
-            issuers_frame_var: self.issuers_frame_var as i64,
-            currency: self.currency.to_string(),
-            issuers: self.issuers.iter().map(ToString::to_string).collect(),
-            signatures: self.signatures.iter().map(ToString::to_string).collect(),
-            hash: self.hash.map(|hash| hash.to_string()),
-            parameters: self.parameters.map(|parameters| parameters.to_string()),
-            previous_hash: self.previous_hash.map(|hash| hash.to_string()),
-            previous_issuer: self.previous_issuer.map(|p| p.to_string()),
-            inner_hash: self.inner_hash.map(|hash| hash.to_string()),
-            dividend: self.dividend.map(|dividend| dividend as u64),
-            identities: self
-                .identities
-                .iter()
-                .map(ToStringObject::to_string_object)
-                .collect(),
-            joiners: self
-                .joiners
-                .iter()
-                .map(ToStringObject::to_string_object)
-                .collect(),
-            actives: self
-                .actives
-                .iter()
-                .map(ToStringObject::to_string_object)
-                .collect(),
-            leavers: self
-                .leavers
-                .iter()
-                .map(ToStringObject::to_string_object)
-                .collect(),
-            revoked: self
-                .revoked
-                .iter()
-                .map(|revocation_doc| match revocation_doc {
-                    TextDocumentFormat::Complete(complete_revoc_doc) => {
-                        complete_revoc_doc.to_compact_document().to_string_object()
-                    }
-                    TextDocumentFormat::Compact(compact_revoc_doc) => {
-                        compact_revoc_doc.to_string_object()
-                    }
-                })
-                .collect(),
-            excluded: self.excluded.iter().map(ToString::to_string).collect(),
-            certifications: self
-                .certifications
-                .iter()
-                .map(|cert_doc| match cert_doc {
-                    TextDocumentFormat::Complete(complete_cert_doc) => {
-                        complete_cert_doc.to_compact_document().to_string_object()
-                    }
-                    TextDocumentFormat::Compact(compact_cert_doc) => {
-                        compact_cert_doc.to_string_object()
-                    }
-                })
-                .collect(),
-            transactions: self
-                .transactions
-                .iter()
-                .map(|tx_doc_or_tx_hash| match tx_doc_or_tx_hash {
-                    TxDocOrTxHash::TxDoc(tx_doc) => tx_doc.to_string_object(),
-                    TxDocOrTxHash::TxHash(_) => {
-                        fatal_error!("Try to stringify block without their tx documents")
-                    }
-                })
-                .collect(),
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::certification::CertificationDocumentParser;
-    use super::transaction::TransactionDocumentParser;
-    use super::*;
-    use crate::{Document, VerificationResult};
-
-    #[test]
-    fn generate_and_verify_empty_block() {
-        let mut block = BlockDocument {
-            nonce: 100_010_200_000_006_940,
-            version: 10,
-            number: BlockNumber(174_260),
-            pow_min: 68,
-            time: 1_525_296_873,
-            median_time: 1_525_292_577,
-            members_count: 33,
-            monetary_mass: 15_633_687,
-            unit_base: 0,
-            issuers_count: 8,
-            issuers_frame: 41,
-            issuers_frame_var: 0,
-            currency: CurrencyName(String::from("g1-test")),
-            issuers: vec![PubKey::Ed25519(ed25519::PublicKey::from_base58("39Fnossy1GrndwCnAXGDw3K5UYXhNXAFQe7yhYZp8ELP").unwrap())],
-            signatures: vec![Sig::Ed25519(ed25519::Signature::from_base64("lqXrNOopjM39oM7hgB7Vq13uIohdCuLlhh/q8RVVEZ5UVASphow/GXikCdhbWID19Bn0XrXzTbt/R7akbE9xAg==").unwrap())],
-            hash: None,
-            parameters: None,
-            previous_hash: Some(Hash::from_hex("0000A7D4361B9EBF4CE974A521149A73E8A5DE9B73907AB3BC918726AED7D40A").expect("fail to parse previous_hash")),
-            previous_issuer: Some(PubKey::Ed25519(ed25519::PublicKey::from_base58("EPKuZA1Ek5y8S1AjAmAPtGrVCMFqUGzUEAa7Ei62CY2L").unwrap())),
-            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(),
-            inner_hash_and_nonce_str: String::new(),
-        };
-        // test inner_hash computation
-        block.compute_inner_hash();
-        println!("{}", block.generate_compact_text());
-        assert_eq!(
-            block
-                .inner_hash
-                .expect("Try to get inner_hash of an uncompleted or reduce block !")
-                .to_hex(),
-            "58E4865A47A46E0DF1449AABC449B5406A12047C413D61B5E17F86BE6641E7B0"
-        );
-        // Test signature validity
-        block.fill_inner_hash_and_nonce_str(Some(100_010_200_000_006_940));
-        assert_eq!(block.verify_signatures(), VerificationResult::Valid());
-        // Test hash computation
-        block.compute_hash();
-        assert_eq!(
-            block
-                .hash
-                .expect("Try to get hash of an uncompleted or reduce block !")
-                .0
-                .to_hex(),
-            "00002EE584F36C15D3EB21AAC78E0896C75EF9070E73B4EC33BFA2C3D561EEB2"
-        );
-    }
 
-    #[test]
-    fn generate_and_verify_block() {
-        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 tx1 = 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");
-
-        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");
-
-        let mut block = BlockDocument {
-            nonce: 0,
-            version: 10,
-            number: BlockNumber(107_984),
-            pow_min: 88,
-            time: 1_522_685_861,
-            median_time: 1522683184,
-            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: None,
-            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![TxDocOrTxHash::TxDoc(Box::new(tx1)), TxDocOrTxHash::TxDoc(Box::new(tx2))],
-            inner_hash_and_nonce_str: String::new(),
-        };
-        // test inner_hash computation
-        block.compute_inner_hash();
-        println!("{}", block.generate_compact_text());
-        assert_eq!(
-            block
-                .inner_hash
-                .expect("Try to get inner_hash of an uncompleted or reduce block !")
-                .to_hex(),
-            "C8AB69E33ECE2612EADC7AB30D069B1F1A3D8C95EBBFD50DE583AC8E3666CCA1"
-        );
-        // test generate_compact_text()
-        assert_eq!(
-            block.generate_compact_text(),
-            "Version: 10
-Type: Block
-Currency: g1
-Number: 107984
-PoWMin: 88
-Time: 1522685861
-MedianTime: 1522683184
-UnitBase: 0
-Issuer: DA4PYtXdvQqk1nCaprXH52iMsK5Ahxs1nRWbWKLhpVkQ
-IssuersFrame: 211
-IssuersFrameVar: 0
-DifferentIssuersCount: 42
-PreviousHash: 000001144968D0C3516BE6225E4662F182E28956AF46DD7FB228E3D0F9413FEB
-PreviousIssuer: D3krfq6J9AmfpKnS3gQVYoy7NzGCc61vokteTS8LJ4YH
-MembersCount: 896
-Identities:
-Joiners:
-Actives:
-Leavers:
-Revoked:
-Excluded:
-Certifications:
-6TAzLWuNcSqgNDNpAutrKpPXcGJwy1ZEMeVvZSZNs2e3:CYPsYTdt87Tx6cCiZs9KD4jqPgYxbcVEqVZpRgJ9jjoV:106669:UmseG2XKNwKcY8RFi6gUCT91udGnnNmSh7se10J1jeRVlwf+O2Tyb2Cccot9Dt7BO4+Kx2P6vFJB3oVGGHMxBA==
-Transactions:
-TX:10:1:1:1:1:1:0
-107982-000001242F6DA51C06A915A96C58BAA37AB3D1EB51F6E1C630C707845ACF764B
-8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3
-1002:0:D:8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3:106345
-0:SIG(0)
-1002:0:SIG(CitdnuQgZ45tNFCagay7Wh12gwwHM8VLej1sWmfHWnQX)
-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==
-TX:10:1:1:1:1:1:0
-107982-000001242F6DA51C06A915A96C58BAA37AB3D1EB51F6E1C630C707845ACF764B
-8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3
-1002:0:D:8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3:106614
-0:SIG(0)
-1002:0:SIG(78ZwwgpgdH5uLZLbThUQH7LKwPgjMunYfLiCfUCySkM8)
-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==
-InnerHash: C8AB69E33ECE2612EADC7AB30D069B1F1A3D8C95EBBFD50DE583AC8E3666CCA1
-Nonce: "
-        );
-        // Test signature validity
-        block.fill_inner_hash_and_nonce_str(Some(10_300_000_018_323));
-        assert_eq!(block.verify_signatures(), VerificationResult::Valid());
-        // Test hash computation
-        block.compute_hash();
-        assert_eq!(
-            block
-                .hash
-                .expect("Try to get hash of an uncompleted or reduce block !")
-                .0
-                .to_hex(),
-            "000004F8B84A3590243BA562E5F2BA379F55A0B387C5D6FAC1022DFF7FFE6014"
-        );
-    }
-
-    #[test]
-    fn generate_and_verify_block_2() {
-        let ms1 = MembershipDocumentParser::parse(
-            "Version: 10
-Type: Membership
-Currency: g1
-Issuer: 4VZkro3N7VonygybESHngKUABA6gSrbW77Ktb94zE969
-Block: 165645-000002D30130881939961A38D51CA233B3C696AA604439036DB1AAA4ED5046D2
-Membership: IN
-UserID: piaaf31
-CertTS: 74077-0000022816648B2F7801E059F67CCD0C023FF0ED84459D52C70494D74DDCC6F6
-gvaZ1QnJf8FjjRDJ0cYusgpBgQ8r0NqEz39BooH6DtIrgX+WTeXuLSnjZDl35VCBjokvyjry+v0OkTT8FKpABA==",
-        )
-        .expect("Fail to parse ms1");
-
-        let tx1 = TransactionDocumentParser::parse(
-            "Version: 10
-Type: Transaction
-Currency: g1
-Blockstamp: 165645-000002D30130881939961A38D51CA233B3C696AA604439036DB1AAA4ED5046D2
-Locktime: 0
-Issuers:
-51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2
-Inputs:
-1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:163766
-1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164040
-1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164320
-1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164584
-1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164849
-1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:165118
-1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:165389
-Unlocks:
-0:SIG(0)
-1:SIG(0)
-2:SIG(0)
-3:SIG(0)
-4:SIG(0)
-5:SIG(0)
-6:SIG(0)
-Outputs:
-7000:0:SIG(98wxzS683Tc1WWm1YxpL5WpxS7wBa1mZBccKSsYpaant)
-28:0:SIG(51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2)
-Comment: Panier mixte plus 40 pommes merci
-7o/yIh0BNSAv5pNmHz04uUBl8TuP2s4HRFMtKeGFQfXNYJPUyJTP/dj6hdrgKtJkm5dCfbxT4KRy6wJf+dj1Cw==",
-        )
-        .expect("Fail to parse tx1");
-
-        let tx2 = TransactionDocumentParser::parse(
-            "Version: 10
-Type: Transaction
-Currency: g1
-Blockstamp: 165645-000002D30130881939961A38D51CA233B3C696AA604439036DB1AAA4ED5046D2
-Locktime: 0
-Issuers:
-3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX
-Inputs:
-1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:148827
-1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149100
-1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149370
-1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149664
-1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149943
-1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:150222
-Unlocks:
-0:SIG(0)
-1:SIG(0)
-2:SIG(0)
-3:SIG(0)
-4:SIG(0)
-5:SIG(0)
-Outputs:
-6000:0:SIG(AopwTfXhj8VqZReFJYGGWnoWnXNj3RgaqFcGGywXpZrD)
-12:0:SIG(3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX)
-Comment: En reglement de tes bons bocaux de fruits et legumes
-nxr4exGrt16jteN9ZX3XZPP9l+X0OUbZ1o/QjE1hbWQNtVU3HhH9SJoEvNj2iVl3gCRr9u2OA9uj9vCyUDyjAg==
-",
-        )
-        .expect("Fail to parse tx2");
-
-        let mut block = BlockDocument {
-            nonce: 0,
-            version: 10,
-            number: BlockNumber(165_647),
-            pow_min: 90,
-            time: 1_540_633_175,
-            median_time: 1_540_627_811,
-            members_count: 1402,
-            monetary_mass: 386_008_811,
-            unit_base: 0,
-            issuers_count: 37,
-            issuers_frame: 186,
-            issuers_frame_var: 0,
-            currency: CurrencyName(String::from("g1")),
-            issuers: vec![PubKey::Ed25519(ed25519::PublicKey::from_base58("A4pc9Uuk4NXkWG8CibicjjPpEPdiup1mhjMoRWUZsonq").unwrap())],
-            signatures: vec![Sig::Ed25519(ed25519::Signature::from_base64("2Z/+9ADdZvHXs19YR8+qDzgfl8WJlBG5PcbFvBG9TOuUJbjAdxhcgxrFrSRIABGWcCrIgLkB805fZVLP8jOjBA==").unwrap())],
-            hash: None,
-            parameters: None,
-            previous_hash: Some(Hash::from_hex("000003E78FA4133F2C13B416F330C8DFB5A41EB87E37190615DB334F2C914A51").expect("fail to parse previous_hash")),
-            previous_issuer: Some(PubKey::Ed25519(ed25519::PublicKey::from_base58("8NmGZmGjL1LUgJQRg282yQF7KTdQuRNAg8QfSa2qvd65").unwrap())),
-            inner_hash: None,//Some(Hash::from_hex("3B49ECC1475549CFD94CA7B399311548A0FD0EC93C8EDD5670DAA5A958A41846").expect("fail to parse inner_hash")),
-            dividend: None,
-            identities: vec![],
-            joiners: vec![],
-            actives: vec![ms1],
-            leavers: vec![],
-            revoked: vec![],
-            excluded: vec![],
-            certifications: vec![],
-            transactions: vec![TxDocOrTxHash::TxDoc(Box::new(tx1)), TxDocOrTxHash::TxDoc(Box::new(tx2))],
-            inner_hash_and_nonce_str: String::new(),
-        };
-        // test inner_hash computation
-        block.compute_inner_hash();
-        println!("{}", block.generate_compact_text());
-        assert_eq!(
-            block
-                .inner_hash
-                .expect("Try to get inner_hash of an uncompleted or reduce block !")
-                .to_hex(),
-            "3B49ECC1475549CFD94CA7B399311548A0FD0EC93C8EDD5670DAA5A958A41846"
-        );
-        // test generate_compact_text()
-        let block_compact_text = block.generate_compact_text();
-        assert_eq!(
-            block_compact_text,
-            "Version: 10\nType: Block\nCurrency: g1\nNumber: 165647\nPoWMin: 90\nTime: 1540633175\nMedianTime: 1540627811\nUnitBase: 0\nIssuer: A4pc9Uuk4NXkWG8CibicjjPpEPdiup1mhjMoRWUZsonq\nIssuersFrame: 186\nIssuersFrameVar: 0\nDifferentIssuersCount: 37\nPreviousHash: 000003E78FA4133F2C13B416F330C8DFB5A41EB87E37190615DB334F2C914A51\nPreviousIssuer: 8NmGZmGjL1LUgJQRg282yQF7KTdQuRNAg8QfSa2qvd65\nMembersCount: 1402\nIdentities:\nJoiners:\nActives:\n4VZkro3N7VonygybESHngKUABA6gSrbW77Ktb94zE969:gvaZ1QnJf8FjjRDJ0cYusgpBgQ8r0NqEz39BooH6DtIrgX+WTeXuLSnjZDl35VCBjokvyjry+v0OkTT8FKpABA==:165645-000002D30130881939961A38D51CA233B3C696AA604439036DB1AAA4ED5046D2:74077-0000022816648B2F7801E059F67CCD0C023FF0ED84459D52C70494D74DDCC6F6:piaaf31\nLeavers:\nRevoked:\nExcluded:\nCertifications:\nTransactions:\nTX:10:1:7:7:2:1:0\n165645-000002D30130881939961A38D51CA233B3C696AA604439036DB1AAA4ED5046D2\n51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:163766\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164040\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164320\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164584\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164849\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:165118\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:165389\n0:SIG(0)\n1:SIG(0)\n2:SIG(0)\n3:SIG(0)\n4:SIG(0)\n5:SIG(0)\n6:SIG(0)\n7000:0:SIG(98wxzS683Tc1WWm1YxpL5WpxS7wBa1mZBccKSsYpaant)\n28:0:SIG(51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2)\nPanier mixte plus 40 pommes merci\n7o/yIh0BNSAv5pNmHz04uUBl8TuP2s4HRFMtKeGFQfXNYJPUyJTP/dj6hdrgKtJkm5dCfbxT4KRy6wJf+dj1Cw==\nTX:10:1:6:6:2:1:0\n165645-000002D30130881939961A38D51CA233B3C696AA604439036DB1AAA4ED5046D2\n3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX\n1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:148827\n1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149100\n1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149370\n1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149664\n1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149943\n1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:150222\n0:SIG(0)\n1:SIG(0)\n2:SIG(0)\n3:SIG(0)\n4:SIG(0)\n5:SIG(0)\n6000:0:SIG(AopwTfXhj8VqZReFJYGGWnoWnXNj3RgaqFcGGywXpZrD)\n12:0:SIG(3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX)\nEn reglement de tes bons bocaux de fruits et legumes\nnxr4exGrt16jteN9ZX3XZPP9l+X0OUbZ1o/QjE1hbWQNtVU3HhH9SJoEvNj2iVl3gCRr9u2OA9uj9vCyUDyjAg==\nInnerHash: 3B49ECC1475549CFD94CA7B399311548A0FD0EC93C8EDD5670DAA5A958A41846\nNonce: "
-        );
-        // Test signature validity
-        block.fill_inner_hash_and_nonce_str(Some(10_300_000_090_296));
-        assert_eq!(block.verify_signatures(), VerificationResult::Valid());
-        // Test hash computation
-        block.compute_hash();
-        assert_eq!(
-            block
-                .hash
-                .expect("Try to get hash of an uncompleted or reduce block !")
-                .0
-                .to_hex(),
-            "000002026E32A3D649B34968AAF9D03C4F19A5954229C54A801BBB1CD216B230"
-        );
+    fn to_string_object(&self) -> Self::StringObject {
+        match self {
+            BlockDocument::V10(block) => BlockDocumentStringified::V10(block.to_string_object()),
+        }
     }
 }
diff --git a/lib/tools/documents/src/documents/block/v10.rs b/lib/tools/documents/src/documents/block/v10.rs
new file mode 100644
index 0000000000000000000000000000000000000000..f0ffc6b8c0e0e77bd844d818a85ab1307ff705ed
--- /dev/null
+++ b/lib/tools/documents/src/documents/block/v10.rs
@@ -0,0 +1,954 @@
+//  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/>.
+
+//! Wrappers around Block document v10.
+
+use dup_crypto::hashs::Hash;
+use dup_crypto::keys::*;
+use dup_currency_params::genesis_block_params::v10::BlockV10Parameters;
+use dup_currency_params::CurrencyName;
+use durs_common_tools::fatal_error;
+use std::ops::Deref;
+use unwrap::unwrap;
+
+use super::BlockDocumentTrait;
+use crate::blockstamp::Blockstamp;
+use crate::documents::certification::CertificationDocument;
+use crate::documents::identity::IdentityDocument;
+use crate::documents::membership::MembershipDocument;
+use crate::documents::revocation::RevocationDocument;
+use crate::documents::transaction::TransactionDocument;
+use crate::documents::*;
+use crate::text_document_traits::*;
+
+/// Store a transaction document or just its hash.
+#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
+pub enum TxDocOrTxHash {
+    /// Transaction document
+    TxDoc(Box<TransactionDocument>),
+    /// transaction hash
+    TxHash(Hash),
+}
+
+impl TxDocOrTxHash {
+    /// Lightens the TxDocOrTxHash (for example to store it while minimizing the space required)
+    /// lightening consists in transforming the document by its hash.
+    pub fn reduce(&self) -> TxDocOrTxHash {
+        if let TxDocOrTxHash::TxDoc(ref tx_doc) = self {
+            let tx_doc = tx_doc.deref();
+            if let Some(ref hash) = tx_doc.get_hash_opt() {
+                TxDocOrTxHash::TxHash(*hash)
+            } else {
+                TxDocOrTxHash::TxHash(tx_doc.clone().compute_hash())
+            }
+        } else {
+            self.clone()
+        }
+    }
+    /// Get TxDoc variant
+    pub fn unwrap_doc(&self) -> TransactionDocument {
+        if let TxDocOrTxHash::TxDoc(ref tx_doc) = self {
+            tx_doc.deref().clone()
+        } else {
+            fatal_error!("Try to unwrap_doc() in a TxHash() variant of TxDocOrTxHash !")
+        }
+    }
+}
+
+/// Wrap a Block document.
+///
+/// Must be created by parsing a text document or using a builder.
+#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
+pub struct BlockDocumentV10 {
+    /// Version
+    pub version: u32,
+    /// Nonce
+    pub nonce: u64,
+    /// number
+    pub number: BlockNumber,
+    /// Minimal proof of work difficulty
+    pub pow_min: usize,
+    /// Local time of the block issuer
+    pub time: u64,
+    /// Average time
+    pub median_time: u64,
+    /// Members count
+    pub members_count: usize,
+    /// Monetary mass
+    pub monetary_mass: usize,
+    /// Unit base (power of ten)
+    pub unit_base: usize,
+    /// Number of compute members in the current frame
+    pub issuers_count: usize,
+    /// Current frame size (in blocks)
+    pub issuers_frame: usize,
+    /// Current frame variation buffer
+    pub issuers_frame_var: isize,
+    /// Currency.
+    pub currency: CurrencyName,
+    /// Document issuer (there should be only one).
+    pub issuers: Vec<PubKey>,
+    /// Document signature (there should be only one).
+    /// This vector is empty, when the block is generated but the proof of work has not yet started
+    pub signatures: Vec<Sig>,
+    /// The hash is None, when the block is generated but the proof of work has not yet started
+    pub hash: Option<BlockHash>,
+    /// Currency parameters (only in genesis block)
+    pub parameters: Option<BlockV10Parameters>,
+    /// Hash of the previous block
+    pub previous_hash: Option<Hash>,
+    /// Issuer of the previous block
+    pub previous_issuer: Option<PubKey>,
+    /// Hash of the deterministic content of the block
+    pub inner_hash: Option<Hash>,
+    /// Amount of new dividend created at this block, None if no dividend is created at this block
+    pub dividend: Option<usize>,
+    /// Identities
+    pub identities: Vec<IdentityDocument>,
+    /// joiners
+    pub joiners: Vec<MembershipDocument>,
+    /// Actives (=renewals)
+    pub actives: Vec<MembershipDocument>,
+    /// Leavers
+    pub leavers: Vec<MembershipDocument>,
+    /// Revokeds
+    pub revoked: Vec<TextDocumentFormat<RevocationDocument>>,
+    /// Excludeds
+    pub excluded: Vec<PubKey>,
+    /// Certifications
+    pub certifications: Vec<TextDocumentFormat<CertificationDocument>>,
+    /// Transactions
+    pub transactions: Vec<TxDocOrTxHash>,
+}
+
+impl BlockDocumentTrait for BlockDocumentV10 {
+    fn common_time(&self) -> u64 {
+        self.median_time
+    }
+    fn compute_hash(&self) -> BlockHash {
+        BlockHash(Hash::compute_str(&self.compute_will_hashed_string()))
+    }
+    fn compute_will_hashed_string(&self) -> String {
+        format!(
+            "{}{}\n",
+            self.compute_will_signed_string(),
+            self.signatures[0]
+        )
+    }
+    fn compute_will_signed_string(&self) -> String {
+        format!(
+            "InnerHash: {}\nNonce: {}\n",
+            self.inner_hash
+                .expect("compute_will_signed_string(): Try to get inner_hash of an uncompleted or reduce block !")
+                .to_hex(),
+            self.nonce
+        )
+    }
+    fn current_frame_size(&self) -> usize {
+        self.issuers_frame
+    }
+    fn generate_compact_inner_text(&self) -> String {
+        let mut identities_str = String::from("");
+        for identity in self.identities.clone() {
+            identities_str.push_str("\n");
+            identities_str.push_str(&identity.generate_compact_text());
+        }
+        let mut joiners_str = String::from("");
+        for joiner in self.joiners.clone() {
+            joiners_str.push_str("\n");
+            joiners_str.push_str(&joiner.generate_compact_text());
+        }
+        let mut actives_str = String::from("");
+        for active in self.actives.clone() {
+            actives_str.push_str("\n");
+            actives_str.push_str(&active.generate_compact_text());
+        }
+        let mut leavers_str = String::from("");
+        for leaver in self.leavers.clone() {
+            leavers_str.push_str("\n");
+            leavers_str.push_str(&leaver.generate_compact_text());
+        }
+        let mut identities_str = String::from("");
+        for identity in self.identities.clone() {
+            identities_str.push_str("\n");
+            identities_str.push_str(&identity.generate_compact_text());
+        }
+        let mut revokeds_str = String::from("");
+        for revocation in self.revoked.clone() {
+            revokeds_str.push_str("\n");
+            revokeds_str.push_str(&revocation.as_compact_text());
+        }
+        let mut excludeds_str = String::from("");
+        for exclusion in self.excluded.clone() {
+            excludeds_str.push_str("\n");
+            excludeds_str.push_str(&exclusion.to_string());
+        }
+        let mut certifications_str = String::from("");
+        for certification in self.certifications.clone() {
+            certifications_str.push_str("\n");
+            certifications_str.push_str(&certification.as_compact_text());
+        }
+        let mut transactions_str = String::from("");
+        for transaction in self.transactions.clone() {
+            if let TxDocOrTxHash::TxDoc(transaction) = transaction {
+                transactions_str.push_str("\n");
+                transactions_str.push_str(&transaction.deref().generate_compact_text());
+            }
+        }
+        let mut dividend_str = String::from("");
+        if let Some(dividend) = self.dividend {
+            if dividend > 0 {
+                dividend_str.push_str("UniversalDividend: ");
+                dividend_str.push_str(&dividend.to_string());
+                dividend_str.push_str("\n");
+            }
+        }
+        let mut parameters_str = String::from("");
+        if let Some(params) = self.parameters {
+            parameters_str.push_str("Parameters: ");
+            parameters_str.push_str(&params.to_string());
+            parameters_str.push_str("\n");
+        }
+        let mut previous_hash_str = String::from("");
+        if self.number.0 > 0 {
+            previous_hash_str.push_str("PreviousHash: ");
+            previous_hash_str.push_str(&unwrap!(self.previous_hash).to_string());
+            previous_hash_str.push_str("\n");
+        }
+        let mut previous_issuer_str = String::from("");
+        if self.number.0 > 0 {
+            previous_issuer_str.push_str("PreviousIssuer: ");
+            previous_issuer_str.push_str(
+                &self
+                    .previous_issuer
+                    .expect("No genesis block must have previous issuer")
+                    .to_string(),
+            );
+            previous_issuer_str.push_str("\n");
+        }
+        format!(
+            "Version: {version}
+Type: Block
+Currency: {currency}
+Number: {block_number}
+PoWMin: {pow_min}
+Time: {time}
+MedianTime: {median_time}
+{dividend}UnitBase: {unit_base}
+Issuer: {issuer}
+IssuersFrame: {issuers_frame}
+IssuersFrameVar: {issuers_frame_var}
+DifferentIssuersCount: {issuers_count}
+{parameters}{previous_hash}{previous_issuer}MembersCount: {members_count}
+Identities:{identities}
+Joiners:{joiners}
+Actives:{actives}
+Leavers:{leavers}
+Revoked:{revoked}
+Excluded:{excluded}
+Certifications:{certifications}
+Transactions:{transactions}
+",
+            version = self.version,
+            currency = self.currency,
+            block_number = self.number,
+            pow_min = self.pow_min,
+            time = self.time,
+            median_time = self.median_time,
+            dividend = dividend_str,
+            unit_base = self.unit_base,
+            issuer = self.issuers[0],
+            issuers_frame = self.issuers_frame,
+            issuers_frame_var = self.issuers_frame_var,
+            issuers_count = self.issuers_count,
+            parameters = parameters_str,
+            previous_hash = previous_hash_str,
+            previous_issuer = previous_issuer_str,
+            members_count = self.members_count,
+            identities = identities_str,
+            joiners = joiners_str,
+            actives = actives_str,
+            leavers = leavers_str,
+            revoked = revokeds_str,
+            excluded = excludeds_str,
+            certifications = certifications_str,
+            transactions = transactions_str,
+        )
+    }
+    fn generate_hash(&mut self) {
+        self.hash = Some(self.compute_hash());
+    }
+    fn generate_inner_hash(&mut self) {
+        self.inner_hash = Some(self.compute_inner_hash());
+    }
+    fn hash(&self) -> Option<BlockHash> {
+        self.hash
+    }
+    fn increment_nonce(&mut self) {
+        self.nonce += 1;
+    }
+    fn inner_hash(&self) -> Option<Hash> {
+        self.inner_hash
+    }
+    fn issuers_count(&self) -> usize {
+        self.issuers_count
+    }
+    fn number(&self) -> BlockNumber {
+        self.number
+    }
+    fn previous_blockstamp(&self) -> Blockstamp {
+        if self.number.0 > 0 {
+            Blockstamp {
+                id: BlockNumber(self.number.0 - 1),
+                hash: BlockHash(unwrap!(self.previous_hash)),
+            }
+        } else {
+            Blockstamp::default()
+        }
+    }
+    fn previous_hash(&self) -> Option<Hash> {
+        self.previous_hash
+    }
+    fn reduce(&mut self) {
+        //self.hash = None;
+        self.inner_hash = None;
+        for i in &mut self.identities {
+            i.reduce();
+        }
+        for i in &mut self.joiners {
+            i.reduce();
+        }
+        for i in &mut self.actives {
+            i.reduce();
+        }
+        for i in &mut self.leavers {
+            i.reduce();
+        }
+        for i in &mut self.transactions {
+            i.reduce();
+        }
+    }
+    fn sign(&mut self, privkey: PrivKey) {
+        self.signatures = vec![privkey.sign(self.compute_will_signed_string().as_bytes())];
+    }
+    fn verify_inner_hash(&self) -> bool {
+        match self.inner_hash {
+            Some(inner_hash) => inner_hash == self.compute_inner_hash(),
+            None => false,
+        }
+    }
+    fn verify_hash(&self) -> bool {
+        match self.hash {
+            Some(hash) => {
+                let expected_hash = self.compute_hash();
+                if hash == expected_hash {
+                    true
+                } else {
+                    warn!(
+                        "Block #{} have invalid hash (expected='{}', actual='{}', datas='{}').",
+                        self.number.0,
+                        expected_hash,
+                        hash,
+                        self.compute_will_hashed_string()
+                    );
+                    false
+                }
+            }
+            None => false,
+        }
+    }
+}
+
+impl Document for BlockDocumentV10 {
+    type PublicKey = PubKey;
+
+    #[inline]
+    fn version(&self) -> u16 {
+        10
+    }
+
+    #[inline]
+    fn currency(&self) -> &str {
+        &self.currency.0
+    }
+
+    #[inline]
+    fn blockstamp(&self) -> Blockstamp {
+        Blockstamp {
+            id: self.number,
+            hash: self
+                .hash
+                .expect("Fatal error : try to get blockstamp of an uncomplete or reduce block !"),
+        }
+    }
+
+    #[inline]
+    fn issuers(&self) -> &Vec<PubKey> {
+        &self.issuers
+    }
+
+    #[inline]
+    fn signatures(&self) -> &Vec<Sig> {
+        &self.signatures
+    }
+
+    #[inline]
+    fn as_bytes(&self) -> &[u8] {
+        fatal_error!("as_bytes() must not be call for BlockDocumentV10 !")
+    }
+
+    #[inline]
+    fn no_as_bytes(&self) -> bool {
+        true
+    }
+
+    #[inline]
+    fn to_bytes(&self) -> Vec<u8> {
+        self.compute_will_signed_string().as_bytes().to_vec()
+    }
+}
+
+impl CompactTextDocument for BlockDocumentV10 {
+    fn as_compact_text(&self) -> String {
+        let compact_inner_text = self.generate_compact_inner_text();
+        format!(
+            "{}InnerHash: {}\nNonce: ",
+            compact_inner_text,
+            self.inner_hash
+                .expect(
+                    "as_compact_text(): Try to get inner_hash of an uncompleted or reduce block !"
+                )
+                .to_hex()
+        )
+    }
+}
+
+impl TextDocument for BlockDocumentV10 {
+    type CompactTextDocument_ = BlockDocumentV10;
+
+    fn as_text(&self) -> &str {
+        fatal_error!(
+            "Dev error: function not implemented. Please use to_compact_document() instead"
+        );
+    }
+
+    fn to_compact_document(&self) -> Self::CompactTextDocument_ {
+        self.clone()
+    }
+}
+
+impl IntoSpecializedDocument<DUBPDocument> for BlockDocumentV10 {
+    fn into_specialized(self) -> DUBPDocument {
+        DUBPDocument::Block(Box::new(self))
+    }
+}
+
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct BlockDocumentV10Stringified {
+    /// Version
+    pub version: u64,
+    /// Nonce
+    pub nonce: u64,
+    /// number
+    pub number: u64,
+    /// Minimal proof of work difficulty
+    pub pow_min: u64,
+    /// Local time of the block issuer
+    pub time: u64,
+    /// Average time
+    pub median_time: u64,
+    /// Members count
+    pub members_count: u64,
+    /// Monetary mass
+    pub monetary_mass: u64,
+    /// Unit base (power of ten)
+    pub unit_base: u64,
+    /// Number of compute members in the current frame
+    pub issuers_count: u64,
+    /// Current frame size (in blocks)
+    pub issuers_frame: i64,
+    /// Current frame variation buffer
+    pub issuers_frame_var: i64,
+    /// Currency.
+    pub currency: String,
+    /// Document issuer (there should be only one).
+    pub issuers: Vec<String>,
+    /// Document signature (there should be only one).
+    /// This vector is empty, when the block is generated but the proof of work has not yet started
+    pub signatures: Vec<String>,
+    /// The hash is None, when the block is generated but the proof of work has not yet started
+    pub hash: Option<String>,
+    /// Currency parameters (only in genesis block)
+    pub parameters: Option<String>,
+    /// Hash of the previous block
+    pub previous_hash: Option<String>,
+    /// Issuer of the previous block
+    pub previous_issuer: Option<String>,
+    /// Hash of the deterministic content of the block
+    pub inner_hash: Option<String>,
+    /// Amount of new dividend created at this block, None if no dividend is created at this block
+    pub dividend: Option<u64>,
+    /// Identities
+    pub identities: Vec<IdentityStringDocument>,
+    /// joiners
+    pub joiners: Vec<MembershipStringDocument>,
+    /// Actives (=renewals)
+    pub actives: Vec<MembershipStringDocument>,
+    /// Leavers
+    pub leavers: Vec<MembershipStringDocument>,
+    /// Revokeds
+    pub revoked: Vec<CompactRevocationStringDocument>,
+    /// Excludeds
+    pub excluded: Vec<String>,
+    /// Certifications
+    pub certifications: Vec<CompactCertificationStringDocument>,
+    /// Transactions
+    pub transactions: Vec<TransactionDocumentStringified>,
+}
+
+impl ToStringObject for BlockDocumentV10 {
+    type StringObject = BlockDocumentV10Stringified;
+    /// Transforms an object into a json object
+    fn to_string_object(&self) -> BlockDocumentV10Stringified {
+        BlockDocumentV10Stringified {
+            version: u64::from(self.version),
+            nonce: self.nonce,
+            number: u64::from(self.number.0),
+            pow_min: self.pow_min as u64,
+            time: self.time,
+            median_time: self.median_time,
+            members_count: self.members_count as u64,
+            monetary_mass: self.monetary_mass as u64,
+            unit_base: self.unit_base as u64,
+            issuers_count: self.issuers_count as u64,
+            issuers_frame: self.issuers_frame as i64,
+            issuers_frame_var: self.issuers_frame_var as i64,
+            currency: self.currency.to_string(),
+            issuers: self.issuers.iter().map(ToString::to_string).collect(),
+            signatures: self.signatures.iter().map(ToString::to_string).collect(),
+            hash: self.hash.map(|hash| hash.to_string()),
+            parameters: self.parameters.map(|parameters| parameters.to_string()),
+            previous_hash: self.previous_hash.map(|hash| hash.to_string()),
+            previous_issuer: self.previous_issuer.map(|p| p.to_string()),
+            inner_hash: self.inner_hash.map(|hash| hash.to_string()),
+            dividend: self.dividend.map(|dividend| dividend as u64),
+            identities: self
+                .identities
+                .iter()
+                .map(ToStringObject::to_string_object)
+                .collect(),
+            joiners: self
+                .joiners
+                .iter()
+                .map(ToStringObject::to_string_object)
+                .collect(),
+            actives: self
+                .actives
+                .iter()
+                .map(ToStringObject::to_string_object)
+                .collect(),
+            leavers: self
+                .leavers
+                .iter()
+                .map(ToStringObject::to_string_object)
+                .collect(),
+            revoked: self
+                .revoked
+                .iter()
+                .map(|revocation_doc| match revocation_doc {
+                    TextDocumentFormat::Complete(complete_revoc_doc) => {
+                        complete_revoc_doc.to_compact_document().to_string_object()
+                    }
+                    TextDocumentFormat::Compact(compact_revoc_doc) => {
+                        compact_revoc_doc.to_string_object()
+                    }
+                })
+                .collect(),
+            excluded: self.excluded.iter().map(ToString::to_string).collect(),
+            certifications: self
+                .certifications
+                .iter()
+                .map(|cert_doc| match cert_doc {
+                    TextDocumentFormat::Complete(complete_cert_doc) => {
+                        complete_cert_doc.to_compact_document().to_string_object()
+                    }
+                    TextDocumentFormat::Compact(compact_cert_doc) => {
+                        compact_cert_doc.to_string_object()
+                    }
+                })
+                .collect(),
+            transactions: self
+                .transactions
+                .iter()
+                .map(|tx_doc_or_tx_hash| match tx_doc_or_tx_hash {
+                    TxDocOrTxHash::TxDoc(tx_doc) => tx_doc.to_string_object(),
+                    TxDocOrTxHash::TxHash(_) => {
+                        fatal_error!("Try to stringify block without their tx documents")
+                    }
+                })
+                .collect(),
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::certification::CertificationDocumentParser;
+    use super::transaction::TransactionDocumentParser;
+    use super::*;
+    use crate::{Document, VerificationResult};
+
+    #[test]
+    fn generate_and_verify_empty_block() {
+        let mut block = BlockDocumentV10 {
+            nonce: 100_010_200_000_006_940,
+            version: 10,
+            number: BlockNumber(174_260),
+            pow_min: 68,
+            time: 1_525_296_873,
+            median_time: 1_525_292_577,
+            members_count: 33,
+            monetary_mass: 15_633_687,
+            unit_base: 0,
+            issuers_count: 8,
+            issuers_frame: 41,
+            issuers_frame_var: 0,
+            currency: CurrencyName(String::from("g1-test")),
+            issuers: vec![PubKey::Ed25519(ed25519::PublicKey::from_base58("39Fnossy1GrndwCnAXGDw3K5UYXhNXAFQe7yhYZp8ELP").unwrap())],
+            signatures: vec![Sig::Ed25519(ed25519::Signature::from_base64("lqXrNOopjM39oM7hgB7Vq13uIohdCuLlhh/q8RVVEZ5UVASphow/GXikCdhbWID19Bn0XrXzTbt/R7akbE9xAg==").unwrap())],
+            hash: None,
+            parameters: None,
+            previous_hash: Some(Hash::from_hex("0000A7D4361B9EBF4CE974A521149A73E8A5DE9B73907AB3BC918726AED7D40A").expect("fail to parse previous_hash")),
+            previous_issuer: Some(PubKey::Ed25519(ed25519::PublicKey::from_base58("EPKuZA1Ek5y8S1AjAmAPtGrVCMFqUGzUEAa7Ei62CY2L").unwrap())),
+            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(),
+        };
+        // test inner_hash computation
+        block.generate_inner_hash();
+        println!("{}", block.generate_compact_text());
+        assert_eq!(
+            block
+                .inner_hash
+                .expect("tests::generate_and_verify_empty_block: Try to get inner_hash of an uncompleted or reduce block !")
+                .to_hex(),
+            "58E4865A47A46E0DF1449AABC449B5406A12047C413D61B5E17F86BE6641E7B0"
+        );
+        // Test signature validity
+        assert_eq!(block.verify_signatures(), VerificationResult::Valid());
+        // Test hash computation
+        block.generate_hash();
+        assert_eq!(
+            block
+                .hash
+                .expect("Try to get hash of an uncompleted or reduce block !")
+                .0
+                .to_hex(),
+            "00002EE584F36C15D3EB21AAC78E0896C75EF9070E73B4EC33BFA2C3D561EEB2"
+        );
+    }
+
+    #[test]
+    fn generate_and_verify_block() {
+        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 tx1 = 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");
+
+        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");
+
+        let mut block = BlockDocumentV10 {
+            nonce: 10_300_000_018_323,
+            version: 10,
+            number: BlockNumber(107_984),
+            pow_min: 88,
+            time: 1_522_685_861,
+            median_time: 1522683184,
+            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: None,
+            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![TxDocOrTxHash::TxDoc(Box::new(tx1)), TxDocOrTxHash::TxDoc(Box::new(tx2))],
+        };
+        // test inner_hash computation
+        block.generate_inner_hash();
+        println!("{}", block.generate_compact_text());
+        assert_eq!(
+            block
+                .inner_hash
+                .expect("tests::generate_and_verify_block: Try to get inner_hash of an uncompleted or reduce block !")
+                .to_hex(),
+            "C8AB69E33ECE2612EADC7AB30D069B1F1A3D8C95EBBFD50DE583AC8E3666CCA1"
+        );
+        // test generate_compact_text()
+        assert_eq!(
+            block.generate_compact_text(),
+            "Version: 10
+Type: Block
+Currency: g1
+Number: 107984
+PoWMin: 88
+Time: 1522685861
+MedianTime: 1522683184
+UnitBase: 0
+Issuer: DA4PYtXdvQqk1nCaprXH52iMsK5Ahxs1nRWbWKLhpVkQ
+IssuersFrame: 211
+IssuersFrameVar: 0
+DifferentIssuersCount: 42
+PreviousHash: 000001144968D0C3516BE6225E4662F182E28956AF46DD7FB228E3D0F9413FEB
+PreviousIssuer: D3krfq6J9AmfpKnS3gQVYoy7NzGCc61vokteTS8LJ4YH
+MembersCount: 896
+Identities:
+Joiners:
+Actives:
+Leavers:
+Revoked:
+Excluded:
+Certifications:
+6TAzLWuNcSqgNDNpAutrKpPXcGJwy1ZEMeVvZSZNs2e3:CYPsYTdt87Tx6cCiZs9KD4jqPgYxbcVEqVZpRgJ9jjoV:106669:UmseG2XKNwKcY8RFi6gUCT91udGnnNmSh7se10J1jeRVlwf+O2Tyb2Cccot9Dt7BO4+Kx2P6vFJB3oVGGHMxBA==
+Transactions:
+TX:10:1:1:1:1:1:0
+107982-000001242F6DA51C06A915A96C58BAA37AB3D1EB51F6E1C630C707845ACF764B
+8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3
+1002:0:D:8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3:106345
+0:SIG(0)
+1002:0:SIG(CitdnuQgZ45tNFCagay7Wh12gwwHM8VLej1sWmfHWnQX)
+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==
+TX:10:1:1:1:1:1:0
+107982-000001242F6DA51C06A915A96C58BAA37AB3D1EB51F6E1C630C707845ACF764B
+8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3
+1002:0:D:8dkCwvAqSczUjKsoVMDPVbQ3i6bBQeBQYawL87kqTSQ3:106614
+0:SIG(0)
+1002:0:SIG(78ZwwgpgdH5uLZLbThUQH7LKwPgjMunYfLiCfUCySkM8)
+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==
+InnerHash: C8AB69E33ECE2612EADC7AB30D069B1F1A3D8C95EBBFD50DE583AC8E3666CCA1
+Nonce: "
+        );
+        // Test signature validity
+        assert_eq!(block.verify_signatures(), VerificationResult::Valid());
+        // Test hash computation
+        block.generate_hash();
+        assert_eq!(
+            block
+                .hash
+                .expect("Try to get hash of an uncompleted or reduce block !")
+                .0
+                .to_hex(),
+            "000004F8B84A3590243BA562E5F2BA379F55A0B387C5D6FAC1022DFF7FFE6014"
+        );
+    }
+
+    #[test]
+    fn generate_and_verify_block_2() {
+        let ms1 = MembershipDocumentParser::parse(
+            "Version: 10
+Type: Membership
+Currency: g1
+Issuer: 4VZkro3N7VonygybESHngKUABA6gSrbW77Ktb94zE969
+Block: 165645-000002D30130881939961A38D51CA233B3C696AA604439036DB1AAA4ED5046D2
+Membership: IN
+UserID: piaaf31
+CertTS: 74077-0000022816648B2F7801E059F67CCD0C023FF0ED84459D52C70494D74DDCC6F6
+gvaZ1QnJf8FjjRDJ0cYusgpBgQ8r0NqEz39BooH6DtIrgX+WTeXuLSnjZDl35VCBjokvyjry+v0OkTT8FKpABA==",
+        )
+        .expect("Fail to parse ms1");
+
+        let tx1 = TransactionDocumentParser::parse(
+            "Version: 10
+Type: Transaction
+Currency: g1
+Blockstamp: 165645-000002D30130881939961A38D51CA233B3C696AA604439036DB1AAA4ED5046D2
+Locktime: 0
+Issuers:
+51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2
+Inputs:
+1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:163766
+1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164040
+1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164320
+1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164584
+1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164849
+1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:165118
+1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:165389
+Unlocks:
+0:SIG(0)
+1:SIG(0)
+2:SIG(0)
+3:SIG(0)
+4:SIG(0)
+5:SIG(0)
+6:SIG(0)
+Outputs:
+7000:0:SIG(98wxzS683Tc1WWm1YxpL5WpxS7wBa1mZBccKSsYpaant)
+28:0:SIG(51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2)
+Comment: Panier mixte plus 40 pommes merci
+7o/yIh0BNSAv5pNmHz04uUBl8TuP2s4HRFMtKeGFQfXNYJPUyJTP/dj6hdrgKtJkm5dCfbxT4KRy6wJf+dj1Cw==",
+        )
+        .expect("Fail to parse tx1");
+
+        let tx2 = TransactionDocumentParser::parse(
+            "Version: 10
+Type: Transaction
+Currency: g1
+Blockstamp: 165645-000002D30130881939961A38D51CA233B3C696AA604439036DB1AAA4ED5046D2
+Locktime: 0
+Issuers:
+3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX
+Inputs:
+1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:148827
+1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149100
+1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149370
+1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149664
+1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149943
+1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:150222
+Unlocks:
+0:SIG(0)
+1:SIG(0)
+2:SIG(0)
+3:SIG(0)
+4:SIG(0)
+5:SIG(0)
+Outputs:
+6000:0:SIG(AopwTfXhj8VqZReFJYGGWnoWnXNj3RgaqFcGGywXpZrD)
+12:0:SIG(3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX)
+Comment: En reglement de tes bons bocaux de fruits et legumes
+nxr4exGrt16jteN9ZX3XZPP9l+X0OUbZ1o/QjE1hbWQNtVU3HhH9SJoEvNj2iVl3gCRr9u2OA9uj9vCyUDyjAg==
+",
+        )
+        .expect("Fail to parse tx2");
+
+        let mut block = BlockDocumentV10 {
+            nonce: 10_300_000_090_296,
+            version: 10,
+            number: BlockNumber(165_647),
+            pow_min: 90,
+            time: 1_540_633_175,
+            median_time: 1_540_627_811,
+            members_count: 1402,
+            monetary_mass: 386_008_811,
+            unit_base: 0,
+            issuers_count: 37,
+            issuers_frame: 186,
+            issuers_frame_var: 0,
+            currency: CurrencyName(String::from("g1")),
+            issuers: vec![PubKey::Ed25519(ed25519::PublicKey::from_base58("A4pc9Uuk4NXkWG8CibicjjPpEPdiup1mhjMoRWUZsonq").unwrap())],
+            signatures: vec![Sig::Ed25519(ed25519::Signature::from_base64("2Z/+9ADdZvHXs19YR8+qDzgfl8WJlBG5PcbFvBG9TOuUJbjAdxhcgxrFrSRIABGWcCrIgLkB805fZVLP8jOjBA==").unwrap())],
+            hash: None,
+            parameters: None,
+            previous_hash: Some(Hash::from_hex("000003E78FA4133F2C13B416F330C8DFB5A41EB87E37190615DB334F2C914A51").expect("fail to parse previous_hash")),
+            previous_issuer: Some(PubKey::Ed25519(ed25519::PublicKey::from_base58("8NmGZmGjL1LUgJQRg282yQF7KTdQuRNAg8QfSa2qvd65").unwrap())),
+            inner_hash: None,//Some(Hash::from_hex("3B49ECC1475549CFD94CA7B399311548A0FD0EC93C8EDD5670DAA5A958A41846").expect("fail to parse inner_hash")),
+            dividend: None,
+            identities: vec![],
+            joiners: vec![],
+            actives: vec![ms1],
+            leavers: vec![],
+            revoked: vec![],
+            excluded: vec![],
+            certifications: vec![],
+            transactions: vec![TxDocOrTxHash::TxDoc(Box::new(tx1)), TxDocOrTxHash::TxDoc(Box::new(tx2))],
+        };
+        // test inner_hash computation
+        block.generate_inner_hash();
+        println!("{}", block.generate_compact_text());
+        assert_eq!(
+            block
+                .inner_hash
+                .expect("tests::generate_and_verify_block_2: Try to get inner_hash of an uncompleted or reduce block !")
+                .to_hex(),
+            "3B49ECC1475549CFD94CA7B399311548A0FD0EC93C8EDD5670DAA5A958A41846"
+        );
+        // test generate_compact_text()
+        let block_compact_text = block.generate_compact_text();
+        assert_eq!(
+            block_compact_text,
+            "Version: 10\nType: Block\nCurrency: g1\nNumber: 165647\nPoWMin: 90\nTime: 1540633175\nMedianTime: 1540627811\nUnitBase: 0\nIssuer: A4pc9Uuk4NXkWG8CibicjjPpEPdiup1mhjMoRWUZsonq\nIssuersFrame: 186\nIssuersFrameVar: 0\nDifferentIssuersCount: 37\nPreviousHash: 000003E78FA4133F2C13B416F330C8DFB5A41EB87E37190615DB334F2C914A51\nPreviousIssuer: 8NmGZmGjL1LUgJQRg282yQF7KTdQuRNAg8QfSa2qvd65\nMembersCount: 1402\nIdentities:\nJoiners:\nActives:\n4VZkro3N7VonygybESHngKUABA6gSrbW77Ktb94zE969:gvaZ1QnJf8FjjRDJ0cYusgpBgQ8r0NqEz39BooH6DtIrgX+WTeXuLSnjZDl35VCBjokvyjry+v0OkTT8FKpABA==:165645-000002D30130881939961A38D51CA233B3C696AA604439036DB1AAA4ED5046D2:74077-0000022816648B2F7801E059F67CCD0C023FF0ED84459D52C70494D74DDCC6F6:piaaf31\nLeavers:\nRevoked:\nExcluded:\nCertifications:\nTransactions:\nTX:10:1:7:7:2:1:0\n165645-000002D30130881939961A38D51CA233B3C696AA604439036DB1AAA4ED5046D2\n51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:163766\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164040\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164320\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164584\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:164849\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:165118\n1004:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:165389\n0:SIG(0)\n1:SIG(0)\n2:SIG(0)\n3:SIG(0)\n4:SIG(0)\n5:SIG(0)\n6:SIG(0)\n7000:0:SIG(98wxzS683Tc1WWm1YxpL5WpxS7wBa1mZBccKSsYpaant)\n28:0:SIG(51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2)\nPanier mixte plus 40 pommes merci\n7o/yIh0BNSAv5pNmHz04uUBl8TuP2s4HRFMtKeGFQfXNYJPUyJTP/dj6hdrgKtJkm5dCfbxT4KRy6wJf+dj1Cw==\nTX:10:1:6:6:2:1:0\n165645-000002D30130881939961A38D51CA233B3C696AA604439036DB1AAA4ED5046D2\n3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX\n1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:148827\n1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149100\n1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149370\n1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149664\n1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:149943\n1002:0:D:3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX:150222\n0:SIG(0)\n1:SIG(0)\n2:SIG(0)\n3:SIG(0)\n4:SIG(0)\n5:SIG(0)\n6000:0:SIG(AopwTfXhj8VqZReFJYGGWnoWnXNj3RgaqFcGGywXpZrD)\n12:0:SIG(3Uwq4qNp2A97P1XQueEBCxmnvgtAKMdfrEq6VB7Ph2qX)\nEn reglement de tes bons bocaux de fruits et legumes\nnxr4exGrt16jteN9ZX3XZPP9l+X0OUbZ1o/QjE1hbWQNtVU3HhH9SJoEvNj2iVl3gCRr9u2OA9uj9vCyUDyjAg==\nInnerHash: 3B49ECC1475549CFD94CA7B399311548A0FD0EC93C8EDD5670DAA5A958A41846\nNonce: "
+        );
+        // Test signature validity
+        assert_eq!(block.verify_signatures(), VerificationResult::Valid());
+        // Test hash computation
+        block.generate_hash();
+        assert_eq!(
+            block
+                .hash
+                .expect("Try to get hash of an uncompleted or reduce block !")
+                .0
+                .to_hex(),
+            "000002026E32A3D649B34968AAF9D03C4F19A5954229C54A801BBB1CD216B230"
+        );
+    }
+}
diff --git a/lib/tools/documents/src/documents/certification.rs b/lib/tools/documents/src/documents/certification.rs
index b853ade4291b84f06b9ad2fcaf3322cbfe7a86ee..9726e78e6149f532e0bd79ac1cca74bbc8863a24 100644
--- a/lib/tools/documents/src/documents/certification.rs
+++ b/lib/tools/documents/src/documents/certification.rs
@@ -159,7 +159,6 @@ impl CertificationDocument {
 
 impl Document for CertificationDocument {
     type PublicKey = PubKey;
-    type CurrencyType = str;
 
     fn version(&self) -> u16 {
         10
diff --git a/lib/tools/documents/src/documents/identity.rs b/lib/tools/documents/src/documents/identity.rs
index 15cb0135894126b596220977d7c96c28d4b0755a..f91bed48de217fecfbcb2cf0bdfbee633508f3f1 100644
--- a/lib/tools/documents/src/documents/identity.rs
+++ b/lib/tools/documents/src/documents/identity.rs
@@ -88,7 +88,6 @@ impl IdentityDocument {
 
 impl Document for IdentityDocument {
     type PublicKey = PubKey;
-    type CurrencyType = str;
 
     fn version(&self) -> u16 {
         10
diff --git a/lib/tools/documents/src/documents/membership.rs b/lib/tools/documents/src/documents/membership.rs
index 528772f56f0b535d3f5d8856957431cf91f28423..90810d8ee11d165fb405ac53e80bc5ef618d9724 100644
--- a/lib/tools/documents/src/documents/membership.rs
+++ b/lib/tools/documents/src/documents/membership.rs
@@ -141,7 +141,6 @@ impl MembershipDocument {
 
 impl Document for MembershipDocument {
     type PublicKey = PubKey;
-    type CurrencyType = str;
 
     fn version(&self) -> u16 {
         10
diff --git a/lib/tools/documents/src/documents/mod.rs b/lib/tools/documents/src/documents/mod.rs
index c2535657228556b52ac7c2f1074cad44bc1c08fe..db92485f286c3164b151509b23c9e14490c568c7 100644
--- a/lib/tools/documents/src/documents/mod.rs
+++ b/lib/tools/documents/src/documents/mod.rs
@@ -39,7 +39,7 @@ pub mod transaction;
 #[derive(Debug, Clone, Serialize, Deserialize)]
 pub enum DUBPDocument {
     /// Block document.
-    Block(Box<BlockDocument>),
+    Block(Box<BlockDocumentV10>),
 
     /// Transaction document.
     Transaction(Box<TransactionDocument>),
@@ -61,7 +61,7 @@ pub enum DUBPDocument {
 #[derive(Debug, Clone, Serialize, Deserialize)]
 pub enum DUBPDocumentStr {
     /// Block document (not yet implemented)
-    Block(Box<BlockDocumentStringified>),
+    Block(Box<BlockDocumentV10Stringified>),
 
     /// Transaction document.
     Transaction(Box<TransactionDocumentStringified>),
@@ -172,7 +172,6 @@ mod tests {
 
     impl Document for PlainTextDocument {
         type PublicKey = PubKey;
-        type CurrencyType = str;
 
         fn version(&self) -> u16 {
             unimplemented!()
diff --git a/lib/tools/documents/src/documents/revocation.rs b/lib/tools/documents/src/documents/revocation.rs
index 37ee248f6f4ccefc8fa64d005b1dec5356d7febe..9d64bbb88b0a8c553fe01faf69a54ae3571b0eca 100644
--- a/lib/tools/documents/src/documents/revocation.rs
+++ b/lib/tools/documents/src/documents/revocation.rs
@@ -127,7 +127,6 @@ impl RevocationDocument {
 
 impl Document for RevocationDocument {
     type PublicKey = PubKey;
-    type CurrencyType = str;
 
     fn version(&self) -> u16 {
         10
diff --git a/lib/tools/documents/src/documents/transaction.rs b/lib/tools/documents/src/documents/transaction.rs
index 3f237bed6a6bafc730d7a8d2b84b6a1e92ebde7a..c293fa75bff576ee2c8727f36b15255a336c95b9 100644
--- a/lib/tools/documents/src/documents/transaction.rs
+++ b/lib/tools/documents/src/documents/transaction.rs
@@ -648,7 +648,6 @@ impl TransactionDocument {
 
 impl Document for TransactionDocument {
     type PublicKey = PubKey;
-    type CurrencyType = str;
 
     fn version(&self) -> u16 {
         10
diff --git a/lib/tools/documents/src/lib.rs b/lib/tools/documents/src/lib.rs
index 282c50f61560c24d5d5fb297150bbb7b96b41cc1..e0778c898b68fc731cc9f3435fd6a8804b4319ab 100644
--- a/lib/tools/documents/src/lib.rs
+++ b/lib/tools/documents/src/lib.rs
@@ -152,26 +152,46 @@ impl Debug for BlockHash {
 pub trait Document: Debug + Clone + PartialEq + Eq {
     /// Type of the `PublicKey` used by the document.
     type PublicKey: PublicKey;
-    /// Data type of the currency code used by the document.
-    type CurrencyType: ?Sized;
 
-    /// Get document version.
-    fn version(&self) -> u16;
-
-    /// Get document currency.
-    fn currency(&self) -> &Self::CurrencyType;
+    /// Get document as bytes for signature verification.
+    fn as_bytes(&self) -> &[u8];
 
     /// Get document blockstamp
     fn blockstamp(&self) -> Blockstamp;
 
+    /// Get document currency name.
+    fn currency(&self) -> &str;
+
     /// Iterate over document issuers.
     fn issuers(&self) -> &Vec<Self::PublicKey>;
 
+    /// Some documents do not directly store the sequence of bytes that will be signed but generate
+    // it on request, so these types of documents cannot provide a reference to the signed bytes.
+    fn no_as_bytes(&self) -> bool {
+        false
+    }
+
+    /// Get document to bytes for signature verification.
+    fn to_bytes(&self) -> Vec<u8> {
+        self.as_bytes().to_vec()
+    }
+
     /// Iterate over document signatures.
     fn signatures(&self) -> &Vec<<Self::PublicKey as PublicKey>::Signature>;
 
-    /// Get document as bytes for signature verification.
-    fn as_bytes(&self) -> &[u8];
+    /// Verify one signature
+    #[inline]
+    fn verify_one_signature(
+        &self,
+        public_key: &Self::PublicKey,
+        signature: &<Self::PublicKey as PublicKey>::Signature,
+    ) -> bool {
+        if self.no_as_bytes() {
+            public_key.verify(&self.to_bytes(), signature)
+        } else {
+            public_key.verify(self.as_bytes(), signature)
+        }
+    }
 
     /// Verify signatures of document content (as text format)
     fn verify_signatures(&self) -> VerificationResult {
@@ -183,11 +203,12 @@ pub trait Document: Debug + Clone + PartialEq + Eq {
         } else {
             let issuers = self.issuers();
             let signatures = self.signatures();
+
             let mismatches: Vec<_> = issuers
                 .iter()
                 .zip(signatures)
                 .enumerate()
-                .filter(|&(_, (key, signature))| !key.verify(self.as_bytes(), signature))
+                .filter(|&(_, (key, signature))| !self.verify_one_signature(key, signature))
                 .map(|(i, _)| i)
                 .collect();
 
@@ -198,6 +219,9 @@ pub trait Document: Debug + Clone + PartialEq + Eq {
             }
         }
     }
+
+    /// Get document version.
+    fn version(&self) -> u16;
 }
 
 /// List of possible results for signature verification.
diff --git a/lib/tools/documents/src/parsers/blocks.rs b/lib/tools/documents/src/parsers/blocks.rs
index 6f5b75eef93e5e3241804f903a4cd77cd45f86e6..8c74f377cafddb644bee542ac2b178526d7a9274 100644
--- a/lib/tools/documents/src/parsers/blocks.rs
+++ b/lib/tools/documents/src/parsers/blocks.rs
@@ -13,7 +13,7 @@
 // You should have received a copy of the GNU Affero General Public License
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-use crate::documents::block::{BlockDocument, TxDocOrTxHash};
+use crate::documents::block::{v10::TxDocOrTxHash, BlockDocument, BlockDocumentV10};
 use crate::documents::membership::MembershipType;
 use crate::parsers::{serde_json_value_to_pest_json_value, DefaultHasher};
 use crate::*;
@@ -46,7 +46,7 @@ pub fn parse_json_block(json_block: &JSONValue<DefaultHasher>) -> Result<BlockDo
 
     let block_number = get_number(json_block, "number")?.trunc() as u32;
 
-    Ok(BlockDocument {
+    Ok(BlockDocument::V10(BlockDocumentV10 {
         version: get_number(json_block, "version")?.trunc() as u32,
         nonce: get_u64(json_block, "nonce")?,
         number: BlockNumber(block_number),
@@ -59,7 +59,7 @@ pub fn parse_json_block(json_block: &JSONValue<DefaultHasher>) -> Result<BlockDo
             .trunc() as usize,
         unit_base: get_number(json_block, "unitbase")?.trunc() as usize,
         issuers_count: get_number(json_block, "issuersCount")?.trunc() as usize,
-        issuers_frame: get_number(json_block, "issuersFrame")?.trunc() as isize,
+        issuers_frame: get_number(json_block, "issuersFrame")?.trunc() as usize,
         issuers_frame_var: get_number(json_block, "issuersFrameVar")?.trunc() as isize,
         currency: CurrencyName(currency.to_owned()),
         issuers: vec![PubKey::Ed25519(ed25519::PublicKey::from_base58(get_str(
@@ -134,13 +134,13 @@ pub fn parse_json_block(json_block: &JSONValue<DefaultHasher>) -> Result<BlockDo
             .map(|tx| crate::parsers::transactions::parse_json_transaction(tx))
             .map(|tx_result| tx_result.map(|tx_doc| TxDocOrTxHash::TxDoc(Box::new(tx_doc))))
             .collect::<Result<Vec<TxDocOrTxHash>, Error>>()?,
-        inner_hash_and_nonce_str: "".to_owned(),
-    })
+    }))
 }
 
 #[cfg(test)]
 mod tests {
     use super::*;
+    use crate::documents::block::BlockDocumentTrait;
 
     #[test]
     fn parse_empty_json_block() {
@@ -180,7 +180,7 @@ mod tests {
         let block_json_value = json_pest_parser::parse_json_string(block_json_str)
             .expect("Fail to parse json block !");
         assert_eq!(
-            BlockDocument {
+            BlockDocument::V10(BlockDocumentV10 {
                 version: 10,
                 nonce: 10200000037108,
                 number: BlockNumber(7),
@@ -231,8 +231,7 @@ mod tests {
                 excluded: vec![],
                 certifications: vec![],
                 transactions: vec![],
-                inner_hash_and_nonce_str: "".to_owned(),
-            },
+            }),
             parse_json_block(&block_json_value).expect("Fail to parse block_json_value !")
         );
     }
@@ -302,7 +301,7 @@ mod tests {
         let block_json_value = json_pest_parser::parse_json_string(block_json_str)
             .expect("Fail to parse json block !");
 
-        let expected_block = BlockDocument {
+        let expected_block = BlockDocument::V10(BlockDocumentV10 {
                 version: 10,
                 nonce: 10100000033688,
                 number: BlockNumber(52),
@@ -353,8 +352,7 @@ mod tests {
                 excluded: vec![],
                 certifications: vec![],
                 transactions: vec![TxDocOrTxHash::TxDoc(Box::new(crate::parsers::tests::first_g1_tx_doc()))],
-                inner_hash_and_nonce_str: "".to_owned(),
-            };
+            });
         assert_eq!(
             expected_block,
             parse_json_block(&block_json_value).expect("Fail to parse block_json_value !")
diff --git a/lib/tools/documents/src/text_document_traits.rs b/lib/tools/documents/src/text_document_traits.rs
index 0c4ce9146cbccc6ec6d157aa597d58dec5a0140e..806ff22a31716404c0887c1cb296ff3cdf045104 100644
--- a/lib/tools/documents/src/text_document_traits.rs
+++ b/lib/tools/documents/src/text_document_traits.rs
@@ -57,7 +57,7 @@ impl<D: TextDocument> CompactTextDocument for TextDocumentFormat<D> {
 }
 
 /// Trait for a V10 document.
-pub trait TextDocument: Document<PublicKey = PubKey, CurrencyType = str> {
+pub trait TextDocument: Document<PublicKey = PubKey> {
     /// Type of associated compact document.
     type CompactTextDocument_: CompactTextDocument;