diff --git a/app/lib/dal/fileDAL.ts b/app/lib/dal/fileDAL.ts
index f9d66fe7ffb5c889d04bf25c927b4b8458207c43..423c07f66d1b32a26a78aa1036fa454de7801f8a 100644
--- a/app/lib/dal/fileDAL.ts
+++ b/app/lib/dal/fileDAL.ts
@@ -1183,6 +1183,7 @@ export class FileDAL implements ServerDAO {
   }
 
   async removePeerByPubkey(pubkey: string) {
+    this.rustServer.removePeerByPubkey(pubkey);
     return this.peerDAL.removePeerByPubkey(pubkey);
   }
 
@@ -1473,6 +1474,7 @@ export class FileDAL implements ServerDAO {
   }
 
   savePeer(peer: DBPeer) {
+    this.rustServer.savePeer(PeerDTO.fromDBPeer(peer));
     return this.peerDAL.savePeer(peer);
   }
 
@@ -1602,6 +1604,7 @@ export class FileDAL implements ServerDAO {
   }
 
   async resetPeers() {
+    this.rustServer.removeAllPeers();
     await this.peerDAL.removeAll();
     return await this.close();
   }
diff --git a/app/modules/ws2p/lib/WS2PCluster.ts b/app/modules/ws2p/lib/WS2PCluster.ts
index bb49f3b0e933680d617dd2df681560dc3a4ac0b6..080150134257750cec254a0684776dca06c92cf0 100644
--- a/app/modules/ws2p/lib/WS2PCluster.ts
+++ b/app/modules/ws2p/lib/WS2PCluster.ts
@@ -25,7 +25,7 @@ import { PeerDTO, WS2PEndpoint } from "../../../lib/dto/PeerDTO";
 import { GlobalFifoPromise } from "../../../service/GlobalFifoPromise";
 import { OtherConstants } from "../../../lib/other_constants";
 import { Key } from "../../../lib/common-libs/crypto/keyring";
-import { verify } from "../../../../neon/lib";
+import { RustServer, verify } from "../../../../neon/lib";
 import { WS2PServerMessageHandler } from "./interface/WS2PServerMessageHandler";
 import { WS2PMessageHandler } from "./impl/WS2PMessageHandler";
 import { CommonConstants } from "../../../lib/common-libs/constants";
@@ -238,6 +238,9 @@ export class WS2PCluster {
       }
     }, WS2PConstants.HEADS_SPREAD_TIMEOUT);
 
+    // Send HEADs to rust server
+    this.server.dal.rustServer.receiveNewHeads(this.newHeads);
+
     this.server.push({
       ws2p: "heads",
       added: this.newHeads,
diff --git a/neon/native/server.d.ts b/neon/native/server.d.ts
index 39f626d27d773af9bea348fa4ee9856e6cc2c159..c65a605b1a53895010362d86abcc8a6aa0fe0838 100644
--- a/neon/native/server.d.ts
+++ b/neon/native/server.d.ts
@@ -2,12 +2,36 @@
 
 import { TransactionDTOV10 } from './transaction';
 
-export class RustServerConf {
-    command: string | null
-    currency: string
-    gva: GvaConf | undefined
-    selfKeypair: string | null
-    txsMempoolSize: number
+export class BlockDTOV10 {
+    version: number;
+    number: number;
+    currency: string;
+    hash: string;
+    inner_hash: string;
+    previousHash: string;
+    issuer: string;
+    previousIssuer: string;
+    dividend: number | null;
+    time: number;
+    powMin: number;
+    unitbase: number;
+    membersCount: number;
+    issuersCount: number;
+    issuersFrame: number;
+    issuersFrameVar: number;
+    identities: string[];
+    joiners: string[];
+    actives: string[];
+    leavers: string[];
+    revoked: string[];
+    excluded: string[];
+    certifications: string[];
+    transactions: TransactionDTOV10[];
+    medianTime: number;
+    nonce: number;
+    parameters: string | null;
+    signature: string;
+    monetaryMass: number;
 }
 
 export class GvaConf {
@@ -24,6 +48,12 @@ export class GvaConf {
     whitelist?: string[];
 }
 
+export class HeadWS2Pv1 {
+    messageV2?: string;
+    sigV2?: string;
+    step?: number;
+}
+
 export class PeerCard {
     version: number
     currency: string
@@ -51,6 +81,14 @@ export class RustDbTx {
     writtenTime: number;
 }
 
+export class RustServerConf {
+    command: string | null
+    currency: string
+    gva: GvaConf | undefined
+    selfKeypair: string | null
+    txsMempoolSize: number
+}
+
 export class TxsHistory {
     sent: RustDbTx[];
     received: RustDbTx[];
@@ -58,54 +96,35 @@ export class TxsHistory {
     pending: TransactionDTOV10[];
 }
 
-export class BlockDTOV10 {
-    version: number;
-    number: number;
-    currency: string;
-    hash: string;
-    inner_hash: string;
-    previousHash: string;
-    issuer: string;
-    previousIssuer: string;
-    dividend: number | null;
-    time: number;
-    powMin: number;
-    unitbase: number;
-    membersCount: number;
-    issuersCount: number;
-    issuersFrame: number;
-    issuersFrameVar: number;
-    identities: string[];
-    joiners: string[];
-    actives: string[];
-    leavers: string[];
-    revoked: string[];
-    excluded: string[];
-    certifications: string[];
-    transactions: TransactionDTOV10[];
-    medianTime: number;
-    nonce: number;
-    parameters: string | null;
-    signature: string;
-    monetaryMass: number;
-}
-
 export class RustServer {
     constructor(conf: RustServerConf, home: string | null);
 
+    // Indexing blockchain
+    revertBlock(block: BlockDTOV10): void;
+    applyBlock(block: BlockDTOV10): void;
+    applyChunkOfBlocks(blocks: BlockDTOV10[]): void;
+    
+    // Rust Endpoints (GVA, etc)
+    getSelfEndpoints(): string[];
+
+    // Txs mempool
     acceptNewTx(tx: TransactionDTOV10, serverPubkey: string): boolean;
     addPendingTx(tx: TransactionDTOV10): void;
     getMempoolTxsFreeRooms(): number;
     getNewPendingTxs(): TransactionDTOV10[];
-    getSelfEndpoints(): string[];
-    getTransactionsHistory(pubkey: string): TxsHistory;
     getTransactionsPending(versionMin: number, medianTime: number): TransactionDTOV10[];
-    getTxByHash(hash: string): TransactionDTOV10 | null;
     removeAllPendingTxs(): void;
     removePendingTxByHash(hash: string): void;
-    revertBlock(block: BlockDTOV10): void;
-    applyBlock(block: BlockDTOV10): void;
-    applyChunkOfBlocks(blocks: BlockDTOV10[]): void;
     trimExpiredNonWrittenTxs(limitTime: number): void;
+
+    // Transactions history (for BMA only)
+    getTransactionsHistory(pubkey: string): TxsHistory;
+    getTxByHash(hash: string): TransactionDTOV10 | null;
+    
+    // WS2Pv1: HEADs and peers
+    receiveNewHeads(heads: HeadWS2Pv1[]): void;
+    removeAllPeers(): void; 
+    removePeerByPubkey(pubkey: string): void;
+    savePeer(peer: PeerCard): void;
     updateSelfPeer(peer: PeerCard): void;
 }
diff --git a/neon/native/src/server.rs b/neon/native/src/server.rs
index 769318dd08b48386215fef45bd5d9c95dddb867f..70a46f68d8ab7f64ce5414150ff6756e04a6cb20 100644
--- a/neon/native/src/server.rs
+++ b/neon/native/src/server.rs
@@ -82,22 +82,50 @@ declare_types! {
                 }.map(|server| RustServer { server })
             )
         }
-        method acceptNewTx(mut cx) {
-            let tx_js = cx.argument::<JsValue>(0)?;
-            let server_pubkey_str = cx.argument::<JsString>(1)?.value();
 
-            let tx_str: TransactionDocumentV10Stringified = neon_serde::from_value(&mut cx, tx_js)?;
-            let tx = into_neon_res(&mut cx, TransactionDocumentV10::from_string_object(&tx_str))?;
-            let server_pubkey = into_neon_res(&mut cx, PublicKey::from_base58(&server_pubkey_str))?;
+        // Indexing blockchain
+        method revertBlock(mut cx) {
+            let block_js = cx.argument::<JsValue>(0)?;
 
-            let this = cx.this();
+            let block_stringified: dubp::block::DubpBlockV10Stringified = neon_serde::from_value(&mut cx, block_js)?;
+
+            let mut this = cx.this();
             let res = {
                 let guard = cx.lock();
-                let server = this.borrow(&guard);
-                server.server.accept_new_tx(tx, server_pubkey)
-            }.map(|accepted| cx.boolean(accepted).upcast());
+                let mut server = this.borrow_mut(&guard);
+                server.server.revert_block(block_stringified)
+            }.map(|()| cx.undefined().upcast());
+            into_neon_res(&mut cx, res)
+        }
+        method applyBlock(mut cx) {
+            let block_js = cx.argument::<JsValue>(0)?;
+
+            let block_stringified: dubp::block::DubpBlockV10Stringified = neon_serde::from_value(&mut cx, block_js)?;
+
+            let mut this = cx.this();
+            let res = {
+                let guard = cx.lock();
+                let mut server = this.borrow_mut(&guard);
+                server.server.apply_block(block_stringified)
+            }.map(|()| cx.undefined().upcast());
             into_neon_res(&mut cx, res)
         }
+        method applyChunkOfBlocks(mut cx) {
+            let blocks_js = cx.argument::<JsValue>(0)?;
+
+            let blocks_stringified: Vec<dubp::block::DubpBlockV10Stringified> = neon_serde::from_value(&mut cx, blocks_js)?;
+
+            let mut this = cx.this();
+            let res = {
+                let guard = cx.lock();
+                let mut server = this.borrow_mut(&guard);
+                server.server.apply_chunk_of_blocks(blocks_stringified)
+            }.map(|()| cx.undefined().upcast());
+            into_neon_res(&mut cx, res)
+        }
+
+
+        // Rust Endpoints (GVA, etc)
         method getSelfEndpoints(mut cx) {
             let this = cx.this();
             let res = {
@@ -114,54 +142,46 @@ declare_types! {
             });
             into_neon_res(&mut cx, res)
         }
-        method getTxByHash(mut cx) {
-            let hash_str = cx.argument::<JsString>(0)?.value();
-            let hash = into_neon_res(&mut cx, Hash::from_hex(&hash_str))?;
+
+
+        // Txs mempool
+        method acceptNewTx(mut cx) {
+            let tx_js = cx.argument::<JsValue>(0)?;
+            let server_pubkey_str = cx.argument::<JsString>(1)?.value();
+
+            let tx_str: TransactionDocumentV10Stringified = neon_serde::from_value(&mut cx, tx_js)?;
+            let tx = into_neon_res(&mut cx, TransactionDocumentV10::from_string_object(&tx_str))?;
+            let server_pubkey = into_neon_res(&mut cx, PublicKey::from_base58(&server_pubkey_str))?;
 
             let this = cx.this();
             let res = {
                 let guard = cx.lock();
                 let server = this.borrow(&guard);
-                server.server.get_tx_by_hash(hash)
-            };
-            match res {
-                Ok(tx_opt) => if let Some((tx, written_block_opt)) = tx_opt {
-                    let tx_js = neon_serde::to_value(&mut cx, &tx.to_string_object())?;
-                    if let Some(written_block) = written_block_opt {
-                        let written_block =  cx.number(written_block.0);
-                        let tx_js = tx_js.downcast_or_throw::<JsObject, _>(&mut cx)?;
-                        tx_js.set(&mut cx, "writtenBlock", written_block)?;
-                    }
-                    Ok(tx_js.upcast())
-                } else {
-                    Ok(cx.null().upcast())
-                },
-                Err(e) => cx.throw_error(format!("{}", e)),
-            }
+                server.server.accept_new_tx(tx, server_pubkey)
+            }.map(|accepted| cx.boolean(accepted).upcast());
+            into_neon_res(&mut cx, res)
         }
-        method removePendingTxByHash(mut cx) {
-            let hash_str = cx.argument::<JsString>(0)?.value();
-            let hash = into_neon_res(&mut cx, Hash::from_hex(&hash_str))?;
+        method addPendingTx(mut cx) {
+            let tx_js = cx.argument::<JsValue>(0)?;
+
+            let tx_str: TransactionDocumentV10Stringified = neon_serde::from_value(&mut cx, tx_js)?;
+            let tx = into_neon_res(&mut cx, TransactionDocumentV10::from_string_object(&tx_str))?;
 
             let this = cx.this();
             let res = {
                 let guard = cx.lock();
                 let server = this.borrow(&guard);
-                server.server.remove_pending_tx_by_hash(hash)
-            }.map(|()| cx.undefined().upcast());
+                server.server.add_pending_tx_force(tx)
+            }.map(|_| cx.undefined().upcast());
             into_neon_res(&mut cx, res)
         }
-        method revertBlock(mut cx) {
-            let block_js = cx.argument::<JsValue>(0)?;
-
-            let block_stringified: dubp::block::DubpBlockV10Stringified = neon_serde::from_value(&mut cx, block_js)?;
-
-            let mut this = cx.this();
+        method getMempoolTxsFreeRooms(mut cx) {
+            let this = cx.this();
             let res = {
                 let guard = cx.lock();
-                let mut server = this.borrow_mut(&guard);
-                server.server.revert_block(block_stringified)
-            }.map(|()| cx.undefined().upcast());
+                let server = this.borrow(&guard);
+                server.server.get_mempool_txs_free_rooms()
+            }.map(|free_rooms| cx.number(free_rooms as f64).upcast());
             into_neon_res(&mut cx, res)
         }
         method getNewPendingTxs(mut cx) {
@@ -197,57 +217,40 @@ declare_types! {
                 Err(e) => cx.throw_error(format!("{}", e)),
             }
         }
-        method trimExpiredNonWrittenTxs(mut cx) {
-            let limit_time = cx.argument::<JsNumber>(0)?.value() as i64;
-
+        method removeAllPendingTxs(mut cx) {
             let this = cx.this();
             let res = {
                 let guard = cx.lock();
                 let server = this.borrow(&guard);
-                server.server.trim_expired_non_written_txs(limit_time)
-            }.map(|()| cx.undefined().upcast());
-            into_neon_res(&mut cx, res)
-        }
-        method applyBlock(mut cx) {
-            let block_js = cx.argument::<JsValue>(0)?;
-
-            let block_stringified: dubp::block::DubpBlockV10Stringified = neon_serde::from_value(&mut cx, block_js)?;
-
-            let mut this = cx.this();
-            let res = {
-                let guard = cx.lock();
-                let mut server = this.borrow_mut(&guard);
-                server.server.apply_block(block_stringified)
+                server.server.remove_all_pending_txs()
             }.map(|()| cx.undefined().upcast());
             into_neon_res(&mut cx, res)
         }
-        method applyChunkOfBlocks(mut cx) {
-            let blocks_js = cx.argument::<JsValue>(0)?;
-
-            let blocks_stringified: Vec<dubp::block::DubpBlockV10Stringified> = neon_serde::from_value(&mut cx, blocks_js)?;
+        method removePendingTxByHash(mut cx) {
+            let hash_str = cx.argument::<JsString>(0)?.value();
+            let hash = into_neon_res(&mut cx, Hash::from_hex(&hash_str))?;
 
-            let mut this = cx.this();
+            let this = cx.this();
             let res = {
                 let guard = cx.lock();
-                let mut server = this.borrow_mut(&guard);
-                server.server.apply_chunk_of_blocks(blocks_stringified)
+                let server = this.borrow(&guard);
+                server.server.remove_pending_tx_by_hash(hash)
             }.map(|()| cx.undefined().upcast());
             into_neon_res(&mut cx, res)
         }
-        method addPendingTx(mut cx) {
-            let tx_js = cx.argument::<JsValue>(0)?;
-
-            let tx_str: TransactionDocumentV10Stringified = neon_serde::from_value(&mut cx, tx_js)?;
-            let tx = into_neon_res(&mut cx, TransactionDocumentV10::from_string_object(&tx_str))?;
+        method trimExpiredNonWrittenTxs(mut cx) {
+            let limit_time = cx.argument::<JsNumber>(0)?.value() as i64;
 
             let this = cx.this();
             let res = {
                 let guard = cx.lock();
                 let server = this.borrow(&guard);
-                server.server.add_pending_tx_force(tx)
-            }.map(|_| cx.undefined().upcast());
+                server.server.trim_expired_non_written_txs(limit_time)
+            }.map(|()| cx.undefined().upcast());
             into_neon_res(&mut cx, res)
         }
+
+        // Transactions history (for BMA only)
         method getTransactionsHistory(mut cx) {
             let pubkey_str = cx.argument::<JsString>(0)?.value();
             let pubkey = into_neon_res(&mut cx, PublicKey::from_base58(&pubkey_str))?;
@@ -281,21 +284,82 @@ declare_types! {
                 Err(e) => cx.throw_error(format!("{}", e)),
             }
         }
-        method getMempoolTxsFreeRooms(mut cx) {
+        method getTxByHash(mut cx) {
+            let hash_str = cx.argument::<JsString>(0)?.value();
+            let hash = into_neon_res(&mut cx, Hash::from_hex(&hash_str))?;
+
             let this = cx.this();
             let res = {
                 let guard = cx.lock();
                 let server = this.borrow(&guard);
-                server.server.get_mempool_txs_free_rooms()
-            }.map(|free_rooms| cx.number(free_rooms as f64).upcast());
+                server.server.get_tx_by_hash(hash)
+            };
+            match res {
+                Ok(tx_opt) => if let Some((tx, written_block_opt)) = tx_opt {
+                    let tx_js = neon_serde::to_value(&mut cx, &tx.to_string_object())?;
+                    if let Some(written_block) = written_block_opt {
+                        let written_block =  cx.number(written_block.0);
+                        let tx_js = tx_js.downcast_or_throw::<JsObject, _>(&mut cx)?;
+                        tx_js.set(&mut cx, "writtenBlock", written_block)?;
+                    }
+                    Ok(tx_js.upcast())
+                } else {
+                    Ok(cx.null().upcast())
+                },
+                Err(e) => cx.throw_error(format!("{}", e)),
+            }
+        }
+
+        // WS2Pv1: HEADs and peers
+        method receiveNewHeads(mut cx) {
+            let heads_js = cx.argument::<JsValue>(0)?;
+
+            let heads_stringified: Vec<HeadWS2Pv1ConfStringified> = neon_serde::from_value(&mut cx, heads_js)?;
+
+            use duniter_server::{DunpNodeIdV1Db, DunpHeadDbV1, KvResult};
+            let heads = into_neon_res(&mut cx, heads_stringified.into_iter().map(|HeadWS2Pv1ConfStringified { message_v2, sig_v2, .. }| {
+                DunpHeadDbV1::from_stringified(&message_v2.unwrap_or_default(), &sig_v2.unwrap_or_default())
+            }).collect::<KvResult<Vec<(DunpNodeIdV1Db, DunpHeadDbV1)>>>())?;
+
+            let this = cx.this();
+            let res = {
+                let guard = cx.lock();
+                let server = this.borrow(&guard);
+                server.server.receive_new_heads(heads)
+            }.map(|()| cx.undefined().upcast());
             into_neon_res(&mut cx, res)
         }
-        method removeAllPendingTxs(mut cx) {
+        method removeAllPeers(mut cx) {
             let this = cx.this();
             let res = {
                 let guard = cx.lock();
                 let server = this.borrow(&guard);
-                server.server.remove_all_pending_txs()
+                server.server.remove_all_peers()
+            }.map(|()| cx.undefined().upcast());
+            into_neon_res(&mut cx, res)
+        }
+        method removePeerByPubkey(mut cx) {
+            let pubkey_str = cx.argument::<JsString>(0)?.value();
+            let pubkey = into_neon_res(&mut cx, PublicKey::from_base58(&pubkey_str))?;
+
+            let this = cx.this();
+            let res = {
+                let guard = cx.lock();
+                let server = this.borrow(&guard);
+                server.server.remove_peer_by_pubkey(pubkey)
+            }.map(|()| cx.undefined().upcast());
+            into_neon_res(&mut cx, res)
+        }
+        method savePeer(mut cx) {
+            let peer_js = cx.argument::<JsValue>(0)?;
+
+            let peer_stringified: PeerCardStringified = neon_serde::from_value(&mut cx, peer_js)?;
+
+            let this = cx.this();
+            let res = {
+                let guard = cx.lock();
+                let server = this.borrow(&guard);
+                server.server.save_peer(peer_stringified)
             }.map(|()| cx.undefined().upcast());
             into_neon_res(&mut cx, res)
         }
@@ -315,24 +379,6 @@ declare_types! {
     }
 }
 
-#[derive(Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-struct RustServerConfStringified {
-    command_name: Option<String>,
-    currency: String,
-    gva: Option<GvaConf>,
-    self_keypair: Option<String>,
-    txs_mempool_size: u32,
-}
-
-#[derive(Deserialize, Serialize)]
-struct TxsHistoryStringified {
-    sent: Vec<DbTx>,
-    received: Vec<DbTx>,
-    sending: Vec<TransactionDocumentV10Stringified>,
-    pending: Vec<TransactionDocumentV10Stringified>,
-}
-
 #[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
 #[serde(rename_all = "camelCase")]
 pub struct DbTx {
@@ -375,3 +421,29 @@ impl DbTx {
         }
     }
 }
+
+#[derive(Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+struct HeadWS2Pv1ConfStringified {
+    message_v2: Option<String>,
+    sig_v2: Option<String>,
+    step: Option<usize>,
+}
+
+#[derive(Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+struct RustServerConfStringified {
+    command_name: Option<String>,
+    currency: String,
+    gva: Option<GvaConf>,
+    self_keypair: Option<String>,
+    txs_mempool_size: u32,
+}
+
+#[derive(Deserialize, Serialize)]
+struct TxsHistoryStringified {
+    sent: Vec<DbTx>,
+    received: Vec<DbTx>,
+    sending: Vec<TransactionDocumentV10Stringified>,
+    pending: Vec<TransactionDocumentV10Stringified>,
+}
diff --git a/rust-libs/duniter-dbs/src/databases.rs b/rust-libs/duniter-dbs/src/databases.rs
index e459678400aa7193b167a1e585f2fb30cabe973d..1c49eafdf9c13bc331d7608754d4a7207a92bd9e 100644
--- a/rust-libs/duniter-dbs/src/databases.rs
+++ b/rust-libs/duniter-dbs/src/databases.rs
@@ -16,5 +16,6 @@
 pub mod bc_v1;
 pub mod bc_v2;
 pub mod cm_v1;
+pub mod dunp_v1;
 pub mod gva_v1;
 pub mod txs_mp_v2;
diff --git a/rust-libs/duniter-dbs/src/databases/cm_v1.rs b/rust-libs/duniter-dbs/src/databases/cm_v1.rs
index f94dc21764c4be1fb9d3a0060f6737dd17f28e61..9771aff3166742ec579561077204daf714a228ad 100644
--- a/rust-libs/duniter-dbs/src/databases/cm_v1.rs
+++ b/rust-libs/duniter-dbs/src/databases/cm_v1.rs
@@ -18,7 +18,7 @@ use crate::*;
 db_schema!(
     CmV1,
     [
-        //["self_pubkey", self_pubkey, (), PubKeyValV2,],
         ["self_peer_old", SelfPeerOld, (), PeerCardDbV1],
+        ["dunp_heads_old", DunpHeadsOld, DunpNodeIdV1Db, DunpHeadDbV1],
     ]
 );
diff --git a/rust-libs/duniter-dbs/src/databases/dunp_v1.rs b/rust-libs/duniter-dbs/src/databases/dunp_v1.rs
new file mode 100644
index 0000000000000000000000000000000000000000..86e4b320a356eb5c08979cbda2c3b5f4e80383d5
--- /dev/null
+++ b/rust-libs/duniter-dbs/src/databases/dunp_v1.rs
@@ -0,0 +1,21 @@
+//  Copyright (C) 2020 Éloïs SANCHEZ.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+use crate::*;
+
+db_schema!(
+    DunpV1,
+    [["peers_old", PeersOld, PubKeyKeyV2, PeerCardDbV1],]
+);
diff --git a/rust-libs/duniter-dbs/src/keys.rs b/rust-libs/duniter-dbs/src/keys.rs
index 70afba42bffbfa157e84cf7f9ba1779a1b204863..b5d2db16bd1451130a4bca39686bba24cfd933a1 100644
--- a/rust-libs/duniter-dbs/src/keys.rs
+++ b/rust-libs/duniter-dbs/src/keys.rs
@@ -16,6 +16,7 @@
 pub mod all;
 pub mod block_number;
 pub mod blockstamp;
+pub mod dunp_node_id;
 pub mod hash;
 pub mod pubkey;
 pub mod pubkey_and_sig;
diff --git a/rust-libs/duniter-dbs/src/keys/dunp_node_id.rs b/rust-libs/duniter-dbs/src/keys/dunp_node_id.rs
new file mode 100644
index 0000000000000000000000000000000000000000..e1edbb9693e4b44f95d544990c0116aaf8b4c34c
--- /dev/null
+++ b/rust-libs/duniter-dbs/src/keys/dunp_node_id.rs
@@ -0,0 +1,95 @@
+//  Copyright (C) 2020 Éloïs SANCHEZ.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+use crate::*;
+use std::fmt::Display;
+use uninit::prelude::*;
+
+#[derive(
+    Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, zerocopy::AsBytes, zerocopy::FromBytes,
+)]
+#[repr(transparent)]
+pub struct DunpNodeIdV1Db([u8; 37]); // uuid ++ pubkey
+
+impl DunpNodeIdV1Db {
+    pub fn new(uuid: u32, pubkey: PublicKey) -> Self {
+        let mut buffer = uninit_array![u8; 37];
+        let (uuid_buffer, pubkey_buffer) = buffer.as_out().split_at_out(4);
+
+        uuid_buffer.copy_from_slice(&uuid.to_be_bytes()[..]);
+        pubkey_buffer.copy_from_slice(pubkey.as_ref());
+
+        Self(unsafe { std::mem::transmute(buffer) })
+    }
+    pub fn get_uuid(&self) -> u32 {
+        let mut buffer = uninit_array![u8; 4];
+
+        buffer.as_out().copy_from_slice(&self.0[..4]);
+
+        u32::from_be_bytes(unsafe { std::mem::transmute(buffer) })
+    }
+    pub fn get_pubkey(&self) -> PublicKey {
+        let mut buffer = uninit_array![u8; 33];
+
+        buffer.as_out().copy_from_slice(&self.0[4..]);
+        let bytes: [u8; 33] = unsafe { std::mem::transmute(buffer) };
+
+        PublicKey::try_from(&bytes[..]).unwrap_or_else(|_| unreachable!())
+    }
+}
+
+impl Default for DunpNodeIdV1Db {
+    fn default() -> Self {
+        DunpNodeIdV1Db([0u8; 37])
+    }
+}
+
+impl Display for DunpNodeIdV1Db {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:x}-{}", self.get_uuid(), self.get_pubkey())
+    }
+}
+
+impl KeyAsBytes for DunpNodeIdV1Db {
+    fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T {
+        f(self.0.as_ref())
+    }
+}
+
+impl kv_typed::prelude::FromBytes for DunpNodeIdV1Db {
+    type Err = StringErr;
+
+    fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> {
+        let layout = zerocopy::LayoutVerified::<_, DunpNodeIdV1Db>::new(bytes)
+            .ok_or_else(|| StringErr("corrupted db".to_owned()))?;
+        Ok(*layout)
+    }
+}
+
+impl ToDumpString for DunpNodeIdV1Db {
+    fn to_dump_string(&self) -> String {
+        todo!()
+    }
+}
+
+#[cfg(feature = "explorer")]
+impl ExplorableKey for DunpNodeIdV1Db {
+    fn from_explorer_str(_: &str) -> std::result::Result<Self, StringErr> {
+        unimplemented!()
+    }
+    fn to_explorer_string(&self) -> KvResult<String> {
+        Ok(self.to_string())
+    }
+}
diff --git a/rust-libs/duniter-dbs/src/lib.rs b/rust-libs/duniter-dbs/src/lib.rs
index f96cd188544d5b6de98baf60a4d89ef040443808..a9e2d3dd487f8f620408dc23b15a7c8522987a36 100644
--- a/rust-libs/duniter-dbs/src/lib.rs
+++ b/rust-libs/duniter-dbs/src/lib.rs
@@ -55,6 +55,7 @@ pub use crate::keys::utxo_id::UtxoIdDbV2;
 pub use keys::all::AllKeyV1;
 pub use keys::block_number::BlockNumberKeyV1;
 pub use keys::blockstamp::BlockstampKeyV1;
+pub use keys::dunp_node_id::DunpNodeIdV1Db;
 pub use keys::hash::{HashKeyV1, HashKeyV2};
 pub use keys::pubkey::{PubKeyKeyV1, PubKeyKeyV2};
 pub use keys::pubkey_and_sig::PubKeyAndSigV1;
@@ -69,6 +70,7 @@ pub use values::block_head_db::BlockHeadDbV1;
 pub use values::block_meta::BlockMetaV2;
 pub use values::block_number_array_db::BlockNumberArrayV1;
 pub use values::cindex_db::CIndexDbV1;
+pub use values::dunp_head::DunpHeadDbV1;
 pub use values::gva_idty_db::GvaIdtyDbV1;
 pub use values::idty_db::IdtyDbV2;
 pub use values::iindex_db::IIndexDbV1;
@@ -115,7 +117,8 @@ pub type FileBackend = kv_typed::backend::memory::Mem;
 #[derive(Clone, Debug)]
 pub struct DuniterDbs<B: Backend> {
     pub bc_db_ro: databases::bc_v2::BcV2DbRo<B>,
-    pub cm_db: databases::cm_v1::CmV1Db<MemSingleton>,
+    pub cm_db: databases::cm_v1::CmV1Db<Mem>,
+    pub dunp_db: databases::dunp_v1::DunpV1Db<B>,
     pub gva_db: databases::gva_v1::GvaV1Db<B>,
     pub txs_mp_db: databases::txs_mp_v2::TxsMpV2Db<B>,
 }
@@ -124,11 +127,13 @@ impl DuniterDbs<Mem> {
     pub fn mem() -> KvResult<Self> {
         use databases::bc_v2::BcV2DbWritable as _;
         use databases::cm_v1::CmV1DbWritable as _;
+        use databases::dunp_v1::DunpV1DbWritable as _;
         use databases::gva_v1::GvaV1DbWritable as _;
         use databases::txs_mp_v2::TxsMpV2DbWritable as _;
         Ok(DuniterDbs {
             bc_db_ro: databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?.get_ro_handler(),
-            cm_db: databases::cm_v1::CmV1Db::<MemSingleton>::open(MemSingletonConf::default())?,
+            cm_db: databases::cm_v1::CmV1Db::<Mem>::open(MemConf::default())?,
+            dunp_db: databases::dunp_v1::DunpV1Db::<Mem>::open(MemConf::default())?,
             gva_db: databases::gva_v1::GvaV1Db::<Mem>::open(MemConf::default())?,
             txs_mp_db: databases::txs_mp_v2::TxsMpV2Db::<Mem>::open(MemConf::default())?,
         })
diff --git a/rust-libs/duniter-dbs/src/open_dbs.rs b/rust-libs/duniter-dbs/src/open_dbs.rs
index 0c4795e506fff8971eec53f7dcf6aec0a71d7ba1..014d5aaf6f3f541626677c4944ddfc2e9b4161ae 100644
--- a/rust-libs/duniter-dbs/src/open_dbs.rs
+++ b/rust-libs/duniter-dbs/src/open_dbs.rs
@@ -15,6 +15,7 @@
 
 use crate::databases::bc_v2::BcV2DbWritable as _;
 use crate::databases::cm_v1::CmV1DbWritable as _;
+use crate::databases::dunp_v1::DunpV1DbWritable as _;
 use crate::databases::gva_v1::GvaV1DbWritable as _;
 use crate::databases::txs_mp_v2::TxsMpV2DbWritable as _;
 use crate::*;
@@ -27,8 +28,13 @@ pub fn open_dbs<B: BackendConf>(
             .expect("fail to open BcV2 DB");
     let dbs = DuniterDbs {
         bc_db_ro: bc_db.get_ro_handler(),
-        cm_db: crate::databases::cm_v1::CmV1Db::<MemSingleton>::open(MemSingletonConf::default())
+        cm_db: crate::databases::cm_v1::CmV1Db::<Mem>::open(MemConf::default())
             .expect("fail to open CmV1 DB"),
+        dunp_db: crate::databases::dunp_v1::DunpV1Db::<B>::open(B::gen_backend_conf(
+            "dunp_v1",
+            home_path_opt,
+        ))
+        .expect("fail to open Dunp DB"),
         gva_db: crate::databases::gva_v1::GvaV1Db::<B>::open(B::gen_backend_conf(
             "gva_v1",
             home_path_opt,
diff --git a/rust-libs/duniter-dbs/src/values.rs b/rust-libs/duniter-dbs/src/values.rs
index a0bc4209b094c8d24fb412447c07142e07258f82..27a5ce4fa70dc8404ee320022e08bcb26ba191bc 100644
--- a/rust-libs/duniter-dbs/src/values.rs
+++ b/rust-libs/duniter-dbs/src/values.rs
@@ -18,6 +18,7 @@ pub mod block_head_db;
 pub mod block_meta;
 pub mod block_number_array_db;
 pub mod cindex_db;
+pub mod dunp_head;
 pub mod gva_idty_db;
 pub mod idty_db;
 pub mod iindex_db;
diff --git a/rust-libs/duniter-dbs/src/values/dunp_head.rs b/rust-libs/duniter-dbs/src/values/dunp_head.rs
new file mode 100644
index 0000000000000000000000000000000000000000..2ab352e9b61bdcffba1be8160b0733b0c667b63e
--- /dev/null
+++ b/rust-libs/duniter-dbs/src/values/dunp_head.rs
@@ -0,0 +1,127 @@
+//  Copyright (C) 2020 Éloïs SANCHEZ.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+use crate::*;
+
+#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
+pub struct DunpHeadDbV1 {
+    pub api: String,
+    pub pubkey: PublicKey,
+    pub blockstamp: Blockstamp,
+    pub software: String,
+    pub software_version: String,
+    pub pow_prefix: u32,
+    pub free_member_room: u32,
+    pub free_mirror_room: u32,
+    pub signature: Signature,
+}
+
+impl DunpHeadDbV1 {
+    pub fn from_stringified(message_v2: &str, signature: &str) -> KvResult<(DunpNodeIdV1Db, Self)> {
+        let signature =
+            Signature::from_base64(signature).map_err(|e| KvError::DeserError(e.to_string()))?;
+
+        let strs: SmallVec<[&str; 11]> = message_v2.split(':').collect();
+        if strs.len() < 11 {
+            return Err(KvError::DeserError(
+                "DunpHeadDbV1::from_stringified(): invalid message_v2".to_owned(),
+            ));
+        }
+
+        let uuid =
+            u32::from_str_radix(strs[5], 16).map_err(|e| KvError::DeserError(e.to_string()))?;
+        let pubkey =
+            PublicKey::from_base58(strs[3]).map_err(|e| KvError::DeserError(e.to_string()))?;
+        let blockstamp =
+            Blockstamp::from_str(strs[4]).map_err(|e| KvError::DeserError(e.to_string()))?;
+
+        Ok((
+            DunpNodeIdV1Db::new(uuid, pubkey),
+            DunpHeadDbV1 {
+                api: strs[0].to_owned(),
+                pubkey,
+                blockstamp,
+                software: strs[6].to_owned(),
+                software_version: strs[7].to_owned(),
+                pow_prefix: u32::from_str(strs[8])
+                    .map_err(|e| KvError::DeserError(e.to_string()))?,
+                free_member_room: u32::from_str(strs[9])
+                    .map_err(|e| KvError::DeserError(e.to_string()))?,
+                free_mirror_room: u32::from_str(strs[10])
+                    .map_err(|e| KvError::DeserError(e.to_string()))?,
+                signature,
+            },
+        ))
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_dunp_head_from_stringified() -> KvResult<()> {
+        let message = "WS2POCAIC:HEAD:2:GX1nYVburxeaVP1SCNuhVKwNy6M2h6wPamHhyoSF4Ccn:379783-0000001BB2B88D077605C1330CA60AA222624FAA3BA60566D6CA51A9122376F7:882a5ad1:duniter:1.8.1:1:1:1";
+        let sig = "qBvJ7JZ4i8tKeItmZ/lurzr5O2/jKnB1reoIjEIl5x6sqbAhVsVsHut85yQoP30tURGfVX5FwMhCuC4DvCSFCg==";
+        let (node_id, head) = DunpHeadDbV1::from_stringified(message, sig)?;
+
+        assert_eq!(&format!("{:x}", node_id.get_uuid()), "882a5ad1");
+        assert_eq!(
+            &node_id.get_pubkey().to_string(),
+            "GX1nYVburxeaVP1SCNuhVKwNy6M2h6wPamHhyoSF4Ccn"
+        );
+        assert_eq!(&head.api, "WS2POCAIC");
+        assert_eq!(
+            &head.pubkey.to_string(),
+            "GX1nYVburxeaVP1SCNuhVKwNy6M2h6wPamHhyoSF4Ccn"
+        );
+        assert_eq!(
+            &head.blockstamp.to_string(),
+            "379783-0000001BB2B88D077605C1330CA60AA222624FAA3BA60566D6CA51A9122376F7"
+        );
+        Ok(())
+    }
+}
+
+impl ValueAsBytes for DunpHeadDbV1 {
+    fn as_bytes<T, F: FnMut(&[u8]) -> KvResult<T>>(&self, mut f: F) -> KvResult<T> {
+        let bytes = bincode::serialize(self).map_err(|e| KvError::DeserError(format!("{}", e)))?;
+        f(bytes.as_ref())
+    }
+}
+
+impl kv_typed::prelude::FromBytes for DunpHeadDbV1 {
+    type Err = StringErr;
+
+    fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> {
+        Ok(bincode::deserialize(&bytes).map_err(|e| StringErr(format!("{}: '{:?}'", e, bytes)))?)
+    }
+}
+
+impl ToDumpString for DunpHeadDbV1 {
+    fn to_dump_string(&self) -> String {
+        todo!()
+    }
+}
+
+#[cfg(feature = "explorer")]
+impl ExplorableValue for DunpHeadDbV1 {
+    fn from_explorer_str(_source: &str) -> std::result::Result<Self, StringErr> {
+        unimplemented!()
+    }
+    fn to_explorer_json(&self) -> KvResult<serde_json::Value> {
+        serde_json::to_value(self).map_err(|e| KvError::DeserError(format!("{}", e)))
+    }
+}
diff --git a/rust-libs/duniter-server/src/lib.rs b/rust-libs/duniter-server/src/lib.rs
index 8b340dac3a3071ab0f5beffc71ca91493c0b4368..ac936bfedd8bdc46c702e835e9323baa2ff96362 100644
--- a/rust-libs/duniter-server/src/lib.rs
+++ b/rust-libs/duniter-server/src/lib.rs
@@ -23,7 +23,7 @@
 )]
 
 pub use duniter_conf::DuniterConf;
-pub use duniter_dbs::smallvec;
+pub use duniter_dbs::{kv_typed::prelude::KvResult, smallvec, DunpHeadDbV1, DunpNodeIdV1Db};
 pub use duniter_gva::{GvaConf, GvaModule, PeerCardStringified};
 
 use anyhow::Context;
@@ -41,7 +41,7 @@ use duniter_dbs::{
         txs_mp_v2::TxsMpV2DbReadable,
     },
     kv_typed::prelude::*,
-    HashKeyV2, PendingTxDbV2,
+    HashKeyV2, PendingTxDbV2, PubKeyKeyV2,
 };
 use duniter_dbs::{prelude::*, BlockMetaV2, FileBackend};
 use duniter_gva_dbs_reader::txs_history::TxsHistory;
@@ -250,7 +250,52 @@ impl DuniterServer {
             .execute(move |dbs| txs_mempool.add_pending_tx_force(&dbs.txs_mp_db, &tx))
             .expect("dbs pool disconnected")
     }
-
+    pub fn apply_block(&mut self, block: DubpBlockV10Stringified) -> KvResult<()> {
+        let block = Arc::new(
+            DubpBlockV10::from_string_object(&block)
+                .map_err(|e| KvError::DeserError(format!("{}", e)))?,
+        );
+        self.current = Some(duniter_dbs_write_ops::apply_block::apply_block(
+            &self.bc_db,
+            block.clone(),
+            self.current,
+            &self.dbs_pool,
+            false,
+        )?);
+        apply_block_modules(block, &self.conf, &self.dbs_pool, None)
+    }
+    pub fn apply_chunk_of_blocks(&mut self, blocks: Vec<DubpBlockV10Stringified>) -> KvResult<()> {
+        log::debug!("apply_chunk(#{})", blocks[0].number);
+        let blocks = Arc::from(
+            blocks
+                .into_iter()
+                .map(|block| DubpBlockV10::from_string_object(&block))
+                .collect::<Result<Vec<_>, _>>()
+                .map_err(|e| KvError::DeserError(format!("{}", e)))?,
+        );
+        self.current = Some(duniter_dbs_write_ops::apply_block::apply_chunk(
+            &self.bc_db,
+            self.current,
+            &self.dbs_pool,
+            blocks.clone(),
+        )?);
+        apply_chunk_of_blocks_modules(blocks, &self.conf, &self.dbs_pool, None)
+    }
+    pub fn receive_new_heads(
+        &self,
+        heads: Vec<(duniter_dbs::DunpNodeIdV1Db, duniter_dbs::DunpHeadDbV1)>,
+    ) -> KvResult<()> {
+        self.dbs_pool
+            .execute(move |dbs| {
+                for (dunp_node_id, dunp_head) in heads {
+                    dbs.cm_db
+                        .dunp_heads_old_write()
+                        .upsert(dunp_node_id, dunp_head)?
+                }
+                Ok::<(), KvError>(())
+            })
+            .expect("dbs pool disconnected")
+    }
     pub fn remove_all_pending_txs(&self) -> KvResult<()> {
         self.dbs_pool
             .execute(move |dbs| {
@@ -284,36 +329,39 @@ impl DuniterServer {
         txs_mp_job_handle.join().expect("dbs pool disconnected")?;
         revert_block_modules(block, &self.conf, &self.dbs_pool, None)
     }
-    pub fn apply_block(&mut self, block: DubpBlockV10Stringified) -> KvResult<()> {
-        let block = Arc::new(
-            DubpBlockV10::from_string_object(&block)
-                .map_err(|e| KvError::DeserError(format!("{}", e)))?,
-        );
-        self.current = Some(duniter_dbs_write_ops::apply_block::apply_block(
-            &self.bc_db,
-            block.clone(),
-            self.current,
-            &self.dbs_pool,
-            false,
-        )?);
-        apply_block_modules(block, &self.conf, &self.dbs_pool, None)
+    pub fn remove_all_peers(&self) -> KvResult<()> {
+        use duniter_dbs::databases::dunp_v1::DunpV1DbWritable as _;
+        self.dbs_pool
+            .execute(move |dbs| dbs.dunp_db.peers_old_write().clear())
+            .expect("dbs pool disconnected")
     }
-    pub fn apply_chunk_of_blocks(&mut self, blocks: Vec<DubpBlockV10Stringified>) -> KvResult<()> {
-        log::debug!("apply_chunk(#{})", blocks[0].number);
-        let blocks = Arc::from(
-            blocks
-                .into_iter()
-                .map(|block| DubpBlockV10::from_string_object(&block))
-                .collect::<Result<Vec<_>, _>>()
-                .map_err(|e| KvError::DeserError(format!("{}", e)))?,
-        );
-        self.current = Some(duniter_dbs_write_ops::apply_block::apply_chunk(
-            &self.bc_db,
-            self.current,
-            &self.dbs_pool,
-            blocks.clone(),
-        )?);
-        apply_chunk_of_blocks_modules(blocks, &self.conf, &self.dbs_pool, None)
+    pub fn remove_peer_by_pubkey(&self, pubkey: PublicKey) -> KvResult<()> {
+        use duniter_dbs::databases::dunp_v1::DunpV1DbWritable as _;
+        self.dbs_pool
+            .execute(move |dbs| dbs.dunp_db.peers_old_write().remove(PubKeyKeyV2(pubkey)))
+            .expect("dbs pool disconnected")
+    }
+    pub fn save_peer(&self, new_peer_card: PeerCardStringified) -> anyhow::Result<()> {
+        use dubp::crypto::keys::PublicKey as _;
+        let pubkey = PublicKey::from_base58(&new_peer_card.pubkey)?;
+        use duniter_dbs::databases::dunp_v1::DunpV1DbWritable as _;
+        self.dbs_pool
+            .execute(move |dbs| {
+                dbs.dunp_db.peers_old_write().upsert(
+                    PubKeyKeyV2(pubkey),
+                    duniter_dbs::PeerCardDbV1 {
+                        version: new_peer_card.version,
+                        currency: new_peer_card.currency,
+                        pubkey: new_peer_card.pubkey,
+                        blockstamp: new_peer_card.blockstamp,
+                        endpoints: new_peer_card.endpoints,
+                        status: new_peer_card.status,
+                        signature: new_peer_card.signature,
+                    },
+                )
+            })
+            .expect("dbs pool disconnected")
+            .map_err(|e| e.into())
     }
     pub fn trim_expired_non_written_txs(&self, limit_time: i64) -> KvResult<()> {
         self.dbs_pool
diff --git a/test/dal/basic-dal-tests.ts b/test/dal/basic-dal-tests.ts
index 7891325bc433d04a5fcc0434a52d02a5ca1454f2..a3e39fffca82e792eeebec22d562066c874812d9 100644
--- a/test/dal/basic-dal-tests.ts
+++ b/test/dal/basic-dal-tests.ts
@@ -26,12 +26,14 @@ var constants = require('../../app/lib/constants');
 var mocks = {
   peer1: {
     pubkey: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd',
-      block: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855',
-      currency: 'bb',
-      version: constants.DOCUMENTS_VERSION,
-      endpoints: [
+    blockstamp: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855',
+    currency: 'bb',
+    version: constants.DOCUMENTS_VERSION,
+    endpoints: [
       'BASIC_MERKLED_API localhost 7777'
-    ]
+    ],
+    status: "UP",
+    signature: "T84YUhY5PeOH1cmlxn+UCG0YjYQSnpKRlyHTlsDTLB19QneCAIxDrxx+Yz/VfzXyq3B5ScjpQG5MQ45wI+tZAw==",
   },
   block0: {
     "issuersCount": 0,