From 4da37489b6ff4bd66e781fe2f352007a56155733 Mon Sep 17 00:00:00 2001
From: librelois <c@elo.tf>
Date: Sat, 20 Mar 2021 22:06:58 +0100
Subject: [PATCH] [ref] gva_dbs_reader: create trait DbsReader

---
 Cargo.lock                                    |  13 +-
 rust-libs/duniter-dbs/Cargo.toml              |   2 +-
 rust-libs/modules/gva/Cargo.toml              |   2 +-
 rust-libs/modules/gva/bca/Cargo.toml          |   3 +-
 .../exec_req_type/prepare_simple_payment.rs   |   4 +-
 rust-libs/modules/gva/bca/src/lib.rs          |  38 +--
 rust-libs/modules/gva/dbs-reader/Cargo.toml   |   4 +
 rust-libs/modules/gva/dbs-reader/src/block.rs |  13 +-
 .../gva/dbs-reader/src/current_frame.rs       |   7 +-
 .../modules/gva/dbs-reader/src/find_inputs.rs |  15 +-
 rust-libs/modules/gva/dbs-reader/src/idty.rs  |   9 +-
 rust-libs/modules/gva/dbs-reader/src/lib.rs   | 236 ++++++++++++++++--
 .../modules/gva/dbs-reader/src/txs_history.rs |  10 +-
 .../gva/dbs-reader/src/uds_of_pubkey.rs       |  19 +-
 rust-libs/modules/gva/dbs-reader/src/utxos.rs |   6 +-
 rust-libs/modules/gva/gql/Cargo.toml          |   3 +-
 rust-libs/modules/gva/gql/src/lib.rs          | 101 +-------
 rust-libs/modules/gva/gql/src/schema.rs       |   6 +-
 rust-libs/tools/kv_typed/Cargo.toml           |   2 +-
 19 files changed, 297 insertions(+), 196 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 0e7f2852b..3083bb0c3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1318,6 +1318,7 @@ dependencies = [
  "duniter-dbs",
  "duniter-gva-db",
  "maplit",
+ "mockall",
  "resiter",
  "smallvec",
  "unwrap",
@@ -2330,11 +2331,11 @@ dependencies = [
 
 [[package]]
 name = "mockall"
-version = "0.8.3"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41cabea45a7fc0e37093f4f30a5e2b62602253f91791c057d5f0470c63260c3d"
+checksum = "18d614ad23f9bb59119b8b5670a85c7ba92c5e9adf4385c81ea00c51c8be33d5"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "downcast",
  "fragile",
  "lazy_static",
@@ -2345,11 +2346,11 @@ dependencies = [
 
 [[package]]
 name = "mockall_derive"
-version = "0.8.3"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c461918bf7f59eefb1459252756bf2351a995d6bd510d0b2061bd86bcdabfa6"
+checksum = "5dd4234635bca06fc96c7368d038061e0aae1b00a764dc817e900dc974e3deea"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "proc-macro2",
  "quote",
  "syn",
diff --git a/rust-libs/duniter-dbs/Cargo.toml b/rust-libs/duniter-dbs/Cargo.toml
index 3f2de6bdf..f75ee58ed 100644
--- a/rust-libs/duniter-dbs/Cargo.toml
+++ b/rust-libs/duniter-dbs/Cargo.toml
@@ -19,7 +19,7 @@ chrono = { version = "0.4.15", optional = true }
 dubp = { version = "0.49.0", features = ["duniter"] }
 kv_typed = { path = "../tools/kv_typed", default-features = false }
 log = "0.4.8"
-mockall = { version = "0.8.0", optional = true }
+mockall = { version = "0.9.1", optional = true }
 parking_lot = "0.11.0"
 paste = "1.0.2"
 rand = "0.7.3"
diff --git a/rust-libs/modules/gva/Cargo.toml b/rust-libs/modules/gva/Cargo.toml
index 1a29df632..1dcfcb9ef 100644
--- a/rust-libs/modules/gva/Cargo.toml
+++ b/rust-libs/modules/gva/Cargo.toml
@@ -35,7 +35,7 @@ warp = "0.3"
 
 [dev-dependencies]
 duniter-dbs = { path = "../../duniter-dbs", features = ["mem"] }
-mockall = "0.8.0"
+mockall = "0.9.1"
 serde_json = "1.0.53"
 tokio = { version = "1.2", features = ["macros", "rt-multi-thread", "time"] }
 unwrap = "1.2.1"
diff --git a/rust-libs/modules/gva/bca/Cargo.toml b/rust-libs/modules/gva/bca/Cargo.toml
index 1495e533e..bf9ff0288 100644
--- a/rust-libs/modules/gva/bca/Cargo.toml
+++ b/rust-libs/modules/gva/bca/Cargo.toml
@@ -25,5 +25,6 @@ uninit = "0.4.0"
 
 [dev-dependencies]
 duniter-dbs = { path = "../../../duniter-dbs", features = ["mem"] }
+duniter-gva-dbs-reader = { path = "../dbs-reader", features = ["mock"] }
 tokio = { version = "1.2", features = ["macros", "rt-multi-thread", "time"] }
-mockall = "0.8.0"
+mockall = "0.9.1"
diff --git a/rust-libs/modules/gva/bca/src/exec_req_type/prepare_simple_payment.rs b/rust-libs/modules/gva/bca/src/exec_req_type/prepare_simple_payment.rs
index 05a516a93..825be48be 100644
--- a/rust-libs/modules/gva/bca/src/exec_req_type/prepare_simple_payment.rs
+++ b/rust-libs/modules/gva/bca/src/exec_req_type/prepare_simple_payment.rs
@@ -142,7 +142,7 @@ mod tests {
             .times(1)
             .returning(|_, _| Ok(Some(BlockMetaV2::default())));
         dbs_reader
-            .expect_find_inputs::<BcV2DbRo<FileBackend>, TxsMpV2Db<FileBackend>>()
+            .expect_find_inputs::<TxsMpV2Db<FileBackend>>()
             .times(1)
             .returning(|_, _, _, _, _| Ok((vec![], SourceAmount::default())));
         let bca_executor = create_bca_executor(dbs_reader).expect("fail to create bca executor");
@@ -182,7 +182,7 @@ mod tests {
             .times(1)
             .returning(|_, _| Ok(Some(BlockMetaV2::default())));
         dbs_reader
-            .expect_find_inputs::<BcV2DbRo<FileBackend>, TxsMpV2Db<FileBackend>>()
+            .expect_find_inputs::<TxsMpV2Db<FileBackend>>()
             .times(1)
             .returning(move |_, _, _, _, _| Ok((vec![input], SourceAmount::with_base0(57))));
         let bca_executor = create_bca_executor(dbs_reader).expect("fail to create bca executor");
diff --git a/rust-libs/modules/gva/bca/src/lib.rs b/rust-libs/modules/gva/bca/src/lib.rs
index 56a67384b..1e202b7af 100644
--- a/rust-libs/modules/gva/bca/src/lib.rs
+++ b/rust-libs/modules/gva/bca/src/lib.rs
@@ -37,22 +37,23 @@ use duniter_bca_types::{
 };
 pub use duniter_dbs::kv_typed::prelude::*;
 use duniter_dbs::{FileBackend, SharedDbs};
+use duniter_gva_dbs_reader::DbsReader;
 use futures::{prelude::stream::FuturesUnordered, StreamExt, TryStream, TryStreamExt};
 use once_cell::sync::OnceCell;
 use smallvec::SmallVec;
 use tokio::task::JoinError;
 
 #[cfg(test)]
-use crate::tests::DbsReader;
+use crate::tests::DbsReaderImpl;
 #[cfg(not(test))]
-use duniter_gva_dbs_reader::DbsReader;
+use duniter_gva_dbs_reader::DbsReaderImpl;
 
 static BCA_EXECUTOR: OnceCell<BcaExecutor> = OnceCell::new();
 
 pub fn set_bca_executor(
     currency: String,
     dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>,
-    dbs_reader: DbsReader,
+    dbs_reader: DbsReaderImpl,
     self_keypair: Ed25519KeyPair,
     software_version: &'static str,
     txs_mempool: duniter_mempools::TxsMempool,
@@ -87,7 +88,7 @@ where
 struct BcaExecutor {
     currency: String,
     dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>,
-    dbs_reader: DbsReader,
+    dbs_reader: DbsReaderImpl,
     self_keypair: Ed25519KeyPair,
     software_version: &'static str,
     txs_mempool: duniter_mempools::TxsMempool,
@@ -202,7 +203,7 @@ impl BcaExecutor {
 #[cfg(not(test))]
 impl BcaExecutor {
     #[inline(always)]
-    pub fn dbs_reader(&self) -> DbsReader {
+    pub fn dbs_reader(&self) -> DbsReaderImpl {
         self.dbs_reader
     }
 }
@@ -224,35 +225,14 @@ mod tests {
     pub use duniter_dbs::databases::cm_v1::{CmV1Db, CmV1DbReadable};
     pub use duniter_dbs::databases::txs_mp_v2::{TxsMpV2Db, TxsMpV2DbReadable};
     pub use duniter_dbs::BlockMetaV2;
+    pub use duniter_gva_dbs_reader::MockDbsReader;
     pub use futures::TryStreamExt;
 
-    mockall::mock! {
-        pub DbsReader {
-            fn block(&self, bc_db: &BcV2DbRo<FileBackend>, number: U32BE) -> KvResult<Option<BlockMetaV2>>;
-            fn find_inputs<BcDb: 'static + BcV2DbReadable, TxsMpDb: 'static + TxsMpV2DbReadable>(
-                &self,
-                bc_db: &BcDb,
-                txs_mp_db: &TxsMpDb,
-                amount: SourceAmount,
-                script: &WalletScriptV10,
-                use_mempool_sources: bool,
-            ) -> anyhow::Result<(Vec<TransactionInputV10>, SourceAmount)>;
-            fn get_current_block<CmDb: 'static + CmV1DbReadable>(
-                &self,
-                cm_db: &CmDb,
-            ) -> KvResult<Option<DubpBlockV10>>;
-            fn get_current_block_meta<CmDb: 'static + CmV1DbReadable>(
-                &self,
-                cm_db: &CmDb,
-            ) -> KvResult<Option<BlockMetaV2>>;
-        }
-    }
-
-    pub type DbsReader = duniter_dbs::kv_typed::prelude::Arc<MockDbsReader>;
+    pub type DbsReaderImpl = duniter_dbs::kv_typed::prelude::Arc<MockDbsReader>;
 
     impl BcaExecutor {
         #[inline(always)]
-        pub fn dbs_reader(&self) -> DbsReader {
+        pub fn dbs_reader(&self) -> DbsReaderImpl {
             self.dbs_reader.clone()
         }
     }
diff --git a/rust-libs/modules/gva/dbs-reader/Cargo.toml b/rust-libs/modules/gva/dbs-reader/Cargo.toml
index d6328c88d..a79613616 100644
--- a/rust-libs/modules/gva/dbs-reader/Cargo.toml
+++ b/rust-libs/modules/gva/dbs-reader/Cargo.toml
@@ -11,12 +11,16 @@ edition = "2018"
 [lib]
 path = "src/lib.rs"
 
+[features]
+mock = ["mockall"]
+
 [dependencies]
 anyhow = "1.0.34"
 arrayvec = "0.5.1"
 duniter-dbs = { path = "../../../duniter-dbs" }
 duniter-gva-db = { path = "../db" }
 dubp = { version = "0.49.0", features = ["duniter"] }
+mockall = { version = "0.9.1", optional = true }
 resiter = "0.4.0"
 
 [dev-dependencies]
diff --git a/rust-libs/modules/gva/dbs-reader/src/block.rs b/rust-libs/modules/gva/dbs-reader/src/block.rs
index d71255de0..c4704b4c9 100644
--- a/rust-libs/modules/gva/dbs-reader/src/block.rs
+++ b/rust-libs/modules/gva/dbs-reader/src/block.rs
@@ -35,8 +35,8 @@ impl FromStr for BlockCursor {
     }
 }
 
-impl DbsReader {
-    pub fn block(
+impl DbsReaderImpl {
+    pub(super) fn block_(
         &self,
         bc_db: &BcV2DbRo<FileBackend>,
         number: U32BE,
@@ -44,7 +44,7 @@ impl DbsReader {
         bc_db.blocks_meta().get(&number)
     }
 
-    pub fn blocks(
+    pub(super) fn blocks_(
         &self,
         bc_db: &BcV2DbRo<FileBackend>,
         page_info: PageInfo<BlockCursor>,
@@ -151,15 +151,13 @@ where
 mod tests {
     use super::*;
     use duniter_dbs::databases::bc_v2::BcV2DbWritable;
-    use duniter_gva_db::GvaV1DbWritable;
     use std::num::NonZeroUsize;
 
     #[test]
     fn test_block() -> KvResult<()> {
         let bc_db = duniter_dbs::databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?;
-        let gva_db = duniter_gva_db::GvaV1Db::<Mem>::open(MemConf::default())?;
         let bc_db_ro = bc_db.get_ro_handler();
-        let db_reader = create_dbs_reader(unsafe { std::mem::transmute(&gva_db.get_ro_handler()) });
+        let db_reader = DbsReaderImpl::mem();
 
         bc_db
             .blocks_meta_write()
@@ -176,9 +174,8 @@ mod tests {
     #[test]
     fn test_blocks() -> KvResult<()> {
         let bc_db = duniter_dbs::databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?;
-        let gva_db = duniter_gva_db::GvaV1Db::<Mem>::open(MemConf::default())?;
         let bc_db_ro = bc_db.get_ro_handler();
-        let db_reader = create_dbs_reader(unsafe { std::mem::transmute(&gva_db.get_ro_handler()) });
+        let db_reader = DbsReaderImpl::mem();
 
         for i in 0..20 {
             bc_db.blocks_meta_write().upsert(
diff --git a/rust-libs/modules/gva/dbs-reader/src/current_frame.rs b/rust-libs/modules/gva/dbs-reader/src/current_frame.rs
index 79b739478..cecf4e2c9 100644
--- a/rust-libs/modules/gva/dbs-reader/src/current_frame.rs
+++ b/rust-libs/modules/gva/dbs-reader/src/current_frame.rs
@@ -17,8 +17,11 @@ use duniter_dbs::BlockMetaV2;
 
 use crate::*;
 
-impl DbsReader {
-    pub fn get_current_frame<BcDb: BcV2DbReadable, CmDb: CmV1DbReadable>(
+impl DbsReaderImpl {
+    pub(super) fn get_current_frame_<
+        BcDb: 'static + BcV2DbReadable,
+        CmDb: 'static + CmV1DbReadable,
+    >(
         &self,
         bc_db: &BcDb,
         cm_db: &CmDb,
diff --git a/rust-libs/modules/gva/dbs-reader/src/find_inputs.rs b/rust-libs/modules/gva/dbs-reader/src/find_inputs.rs
index f47df7437..a896ed579 100644
--- a/rust-libs/modules/gva/dbs-reader/src/find_inputs.rs
+++ b/rust-libs/modules/gva/dbs-reader/src/find_inputs.rs
@@ -22,10 +22,10 @@ use dubp::{documents::transaction::TransactionInputV10, wallet::prelude::*};
 
 pub(super) const MIN_AMOUNT: i64 = 100;
 
-impl DbsReader {
-    pub fn find_inputs<BcDb: BcV2DbReadable, TxsMpDb: TxsMpV2DbReadable>(
+impl DbsReaderImpl {
+    pub(super) fn find_inputs_<TxsMpDb: 'static + TxsMpV2DbReadable>(
         &self,
-        bc_db: &BcDb,
+        bc_db: &BcV2DbRo<FileBackend>,
         txs_mp_db: &TxsMpDb,
         amount: SourceAmount,
         script: &WalletScriptV10,
@@ -81,7 +81,7 @@ impl DbsReader {
                     bc_db,
                     issuer,
                     PageInfo::default(),
-                    Some(&pending_uds_bn),
+                    Some(pending_uds_bn),
                     Some(amount - inputs_sum),
                 )?;
                 inputs.extend(uds.into_iter().map(|(block_number, source_amount)| {
@@ -149,6 +149,7 @@ mod tests {
     #[test]
     fn test_find_inputs() -> anyhow::Result<()> {
         let bc_db = duniter_dbs::databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?;
+        let bc_db_ro = bc_db.get_ro_handler();
         let gva_db = duniter_gva_db::GvaV1Db::<Mem>::open(MemConf::default())?;
         let db_reader = create_dbs_reader(unsafe { std::mem::transmute(&gva_db.get_ro_handler()) });
         let txs_mp_db =
@@ -191,7 +192,7 @@ mod tests {
 
         // Gen tx1
         let (inputs, inputs_sum) = db_reader.find_inputs(
-            &bc_db,
+            &bc_db_ro,
             &txs_mp_db,
             SourceAmount::with_base0(550),
             &script,
@@ -210,7 +211,7 @@ mod tests {
 
         // Gen tx2
         let (inputs, inputs_sum) = db_reader.find_inputs(
-            &bc_db,
+            &bc_db_ro,
             &txs_mp_db,
             SourceAmount::with_base0(550),
             &script,
@@ -226,7 +227,7 @@ mod tests {
 
         // Gen tx3 (use pending utxo)
         let (inputs, inputs_sum) = db_reader.find_inputs(
-            &bc_db,
+            &bc_db_ro,
             &txs_mp_db,
             SourceAmount::with_base0(750),
             &script,
diff --git a/rust-libs/modules/gva/dbs-reader/src/idty.rs b/rust-libs/modules/gva/dbs-reader/src/idty.rs
index a65c64f85..4925f9a59 100644
--- a/rust-libs/modules/gva/dbs-reader/src/idty.rs
+++ b/rust-libs/modules/gva/dbs-reader/src/idty.rs
@@ -15,8 +15,8 @@
 
 use crate::*;
 
-impl DbsReader {
-    pub fn idty(
+impl DbsReaderImpl {
+    pub(super) fn idty_(
         &self,
         bc_db: &BcV2DbRo<FileBackend>,
         pubkey: PublicKey,
@@ -32,15 +32,12 @@ impl DbsReader {
 mod tests {
     use super::*;
     use duniter_dbs::databases::bc_v2::BcV2DbWritable;
-    use duniter_gva_db::GvaV1DbWritable;
 
     #[test]
     fn test_idty() -> KvResult<()> {
         let bc_db = duniter_dbs::databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?;
-        let gva_db = duniter_gva_db::GvaV1Db::<Mem>::open(MemConf::default())?;
         let bc_db_ro = bc_db.get_ro_handler();
-        let db_reader = create_dbs_reader(unsafe { std::mem::transmute(&gva_db.get_ro_handler()) });
-
+        let db_reader = DbsReaderImpl::mem();
         let pk = PublicKey::default();
 
         bc_db
diff --git a/rust-libs/modules/gva/dbs-reader/src/lib.rs b/rust-libs/modules/gva/dbs-reader/src/lib.rs
index ad97ef71d..5e94d2296 100644
--- a/rust-libs/modules/gva/dbs-reader/src/lib.rs
+++ b/rust-libs/modules/gva/dbs-reader/src/lib.rs
@@ -69,15 +69,161 @@ impl std::fmt::Display for WrongCursor {
 }
 impl std::error::Error for WrongCursor {}
 
+#[cfg_attr(feature = "mock", mockall::automock)]
+pub trait DbsReader {
+    fn all_uds_of_pubkey(
+        &self,
+        bc_db: &BcV2DbRo<FileBackend>,
+        pubkey: PublicKey,
+        page_info: PageInfo<BlockNumber>,
+    ) -> KvResult<PagedData<uds_of_pubkey::UdsWithSum>>;
+    fn block(&self, bc_db: &BcV2DbRo<FileBackend>, number: U32BE) -> KvResult<Option<BlockMetaV2>>;
+    fn blocks(
+        &self,
+        bc_db: &BcV2DbRo<FileBackend>,
+        page_info: PageInfo<block::BlockCursor>,
+    ) -> KvResult<PagedData<Vec<(block::BlockCursor, BlockMetaV2)>>>;
+    fn find_inputs<TxsMpDb: 'static + TxsMpV2DbReadable>(
+        &self,
+        bc_db: &BcV2DbRo<FileBackend>,
+        txs_mp_db: &TxsMpDb,
+        amount: SourceAmount,
+        script: &WalletScriptV10,
+        use_mempool_sources: bool,
+    ) -> anyhow::Result<(
+        Vec<dubp::documents::transaction::TransactionInputV10>,
+        SourceAmount,
+    )>;
+    fn find_script_utxos<TxsMpDb: 'static + TxsMpV2DbReadable>(
+        &self,
+        txs_mp_db_ro: &TxsMpDb,
+        amount_target_opt: Option<SourceAmount>,
+        page_info: PageInfo<utxos::UtxoCursor>,
+        script: &WalletScriptV10,
+    ) -> anyhow::Result<PagedData<utxos::UtxosWithSum>>;
+    fn first_scripts_utxos(
+        &self,
+        first: usize,
+        scripts: &[WalletScriptV10],
+    ) -> anyhow::Result<Vec<arrayvec::ArrayVec<[utxos::Utxo; utxos::MAX_FIRST_UTXOS]>>>;
+    fn get_account_balance(
+        &self,
+        account_script: &WalletScriptV10,
+    ) -> KvResult<Option<SourceAmountValV2>>;
+    fn get_blockchain_time(&self, block_number: BlockNumber) -> anyhow::Result<u64>;
+    fn get_current_block<CmDb: 'static + CmV1DbReadable>(
+        &self,
+        cm_db: &CmDb,
+    ) -> KvResult<Option<DubpBlockV10>>;
+    fn get_current_block_meta<CmDb: 'static + CmV1DbReadable>(
+        &self,
+        cm_db: &CmDb,
+    ) -> KvResult<Option<BlockMetaV2>>;
+    fn get_current_frame<BcDb: 'static + BcV2DbReadable, CmDb: 'static + CmV1DbReadable>(
+        &self,
+        bc_db: &BcDb,
+        cm_db: &CmDb,
+    ) -> anyhow::Result<Vec<duniter_dbs::BlockMetaV2>>;
+    fn get_current_ud<BcDb: 'static + BcV2DbReadable>(
+        &self,
+        bc_db: &BcDb,
+    ) -> KvResult<Option<SourceAmount>>;
+    fn get_txs_history_bc_received(
+        &self,
+        from: Option<u64>,
+        page_info: PageInfo<txs_history::TxBcCursor>,
+        script_hash: Hash,
+        to: Option<u64>,
+    ) -> KvResult<PagedData<VecDeque<duniter_gva_db::GvaTxDbV1>>>;
+    fn get_txs_history_bc_sent(
+        &self,
+        from: Option<u64>,
+        page_info: PageInfo<txs_history::TxBcCursor>,
+        script_hash: Hash,
+        to: Option<u64>,
+    ) -> KvResult<PagedData<VecDeque<duniter_gva_db::GvaTxDbV1>>>;
+    fn get_txs_history_mempool<TxsMpDb: 'static + TxsMpV2DbReadable>(
+        &self,
+        txs_mp_db_ro: &TxsMpDb,
+        pubkey: PublicKey,
+    ) -> KvResult<(Vec<TransactionDocumentV10>, Vec<TransactionDocumentV10>)>;
+    fn idty(
+        &self,
+        bc_db: &BcV2DbRo<FileBackend>,
+        pubkey: PublicKey,
+    ) -> KvResult<Option<duniter_dbs::IdtyDbV2>>;
+    fn unspent_uds_of_pubkey(
+        &self,
+        bc_db: &BcV2DbRo<FileBackend>,
+        pubkey: PublicKey,
+        page_info: PageInfo<BlockNumber>,
+        bn_to_exclude_opt: Option<std::collections::BTreeSet<BlockNumber>>,
+        amount_target_opt: Option<SourceAmount>,
+    ) -> KvResult<PagedData<uds_of_pubkey::UdsWithSum>>;
+}
+
 #[derive(Clone, Copy, Debug)]
-pub struct DbsReader(&'static GvaV1DbRo<FileBackend>);
+pub struct DbsReaderImpl(&'static GvaV1DbRo<FileBackend>);
 
-pub fn create_dbs_reader(gva_db_ro: &'static GvaV1DbRo<FileBackend>) -> DbsReader {
-    DbsReader(gva_db_ro)
+pub fn create_dbs_reader(gva_db_ro: &'static GvaV1DbRo<FileBackend>) -> DbsReaderImpl {
+    DbsReaderImpl(gva_db_ro)
 }
 
-impl DbsReader {
-    pub fn get_account_balance(
+impl DbsReader for DbsReaderImpl {
+    fn all_uds_of_pubkey(
+        &self,
+        bc_db: &BcV2DbRo<FileBackend>,
+        pubkey: PublicKey,
+        page_info: PageInfo<BlockNumber>,
+    ) -> KvResult<PagedData<uds_of_pubkey::UdsWithSum>> {
+        self.all_uds_of_pubkey_(bc_db, pubkey, page_info)
+    }
+
+    fn block(&self, bc_db: &BcV2DbRo<FileBackend>, number: U32BE) -> KvResult<Option<BlockMetaV2>> {
+        self.block_(bc_db, number)
+    }
+
+    fn blocks(
+        &self,
+        bc_db: &BcV2DbRo<FileBackend>,
+        page_info: PageInfo<block::BlockCursor>,
+    ) -> KvResult<PagedData<Vec<(block::BlockCursor, BlockMetaV2)>>> {
+        self.blocks_(bc_db, page_info)
+    }
+
+    fn find_inputs<TxsMpDb: 'static + TxsMpV2DbReadable>(
+        &self,
+        bc_db: &BcV2DbRo<FileBackend>,
+        txs_mp_db: &TxsMpDb,
+        amount: SourceAmount,
+        script: &WalletScriptV10,
+        use_mempool_sources: bool,
+    ) -> anyhow::Result<(
+        Vec<dubp::documents::transaction::TransactionInputV10>,
+        SourceAmount,
+    )> {
+        self.find_inputs_(bc_db, txs_mp_db, amount, script, use_mempool_sources)
+    }
+
+    fn find_script_utxos<TxsMpDb: 'static + TxsMpV2DbReadable>(
+        &self,
+        txs_mp_db_ro: &TxsMpDb,
+        amount_target_opt: Option<SourceAmount>,
+        page_info: PageInfo<utxos::UtxoCursor>,
+        script: &WalletScriptV10,
+    ) -> anyhow::Result<PagedData<utxos::UtxosWithSum>> {
+        self.find_script_utxos_(txs_mp_db_ro, amount_target_opt, page_info, script)
+    }
+
+    fn first_scripts_utxos(
+        &self,
+        first: usize,
+        scripts: &[WalletScriptV10],
+    ) -> anyhow::Result<Vec<ArrayVec<[utxos::Utxo; utxos::MAX_FIRST_UTXOS]>>> {
+        self.first_scripts_utxos_(first, scripts)
+    }
+
+    fn get_account_balance(
         &self,
         account_script: &WalletScriptV10,
     ) -> KvResult<Option<SourceAmountValV2>> {
@@ -86,40 +232,98 @@ impl DbsReader {
             .get(duniter_dbs::WalletConditionsV2::from_ref(account_script))
     }
 
-    pub fn get_current_block<CmDb: CmV1DbReadable>(
+    fn get_blockchain_time(&self, block_number: BlockNumber) -> anyhow::Result<u64> {
+        Ok(self
+            .0
+            .blockchain_time()
+            .get(&U32BE(block_number.0))?
+            .unwrap_or_else(|| unreachable!()))
+    }
+
+    fn get_current_block<CmDb: CmV1DbReadable>(
         &self,
         cm_db: &CmDb,
     ) -> KvResult<Option<DubpBlockV10>> {
         Ok(cm_db.current_block().get(&())?.map(|db_block| db_block.0))
     }
 
-    pub fn get_current_block_meta<CmDb: CmV1DbReadable>(
+    fn get_current_block_meta<CmDb: CmV1DbReadable>(
         &self,
         cm_db: &CmDb,
     ) -> KvResult<Option<BlockMetaV2>> {
         cm_db.current_block_meta().get(&())
     }
 
-    pub fn get_current_ud<BcDb: BcV2DbReadable>(
+    fn get_current_frame<BcDb: 'static + BcV2DbReadable, CmDb: 'static + CmV1DbReadable>(
         &self,
         bc_db: &BcDb,
-    ) -> KvResult<Option<SourceAmount>> {
+        cm_db: &CmDb,
+    ) -> anyhow::Result<Vec<BlockMetaV2>> {
+        self.get_current_frame_(bc_db, cm_db)
+    }
+
+    fn get_current_ud<BcDb: BcV2DbReadable>(&self, bc_db: &BcDb) -> KvResult<Option<SourceAmount>> {
         bc_db
             .uds_reval()
             .iter_rev(.., |it| it.values().map_ok(|v| v.0).next_res())
     }
 
-    pub fn get_blockchain_time(&self, block_number: BlockNumber) -> anyhow::Result<u64> {
-        Ok(self
-            .0
-            .blockchain_time()
-            .get(&U32BE(block_number.0))?
-            .unwrap_or_else(|| unreachable!()))
+    fn get_txs_history_bc_received(
+        &self,
+        from: Option<u64>,
+        page_info: PageInfo<txs_history::TxBcCursor>,
+        script_hash: Hash,
+        to: Option<u64>,
+    ) -> KvResult<PagedData<VecDeque<GvaTxDbV1>>> {
+        self.get_txs_history_bc_received_(from, page_info, script_hash, to)
+    }
+
+    fn get_txs_history_bc_sent(
+        &self,
+        from: Option<u64>,
+        page_info: PageInfo<txs_history::TxBcCursor>,
+        script_hash: Hash,
+        to: Option<u64>,
+    ) -> KvResult<PagedData<VecDeque<GvaTxDbV1>>> {
+        self.get_txs_history_bc_sent_(from, page_info, script_hash, to)
+    }
+
+    fn get_txs_history_mempool<TxsMpDb: 'static + TxsMpV2DbReadable>(
+        &self,
+        txs_mp_db_ro: &TxsMpDb,
+        pubkey: PublicKey,
+    ) -> KvResult<(Vec<TransactionDocumentV10>, Vec<TransactionDocumentV10>)> {
+        self.get_txs_history_mempool_(txs_mp_db_ro, pubkey)
+    }
+
+    fn idty(
+        &self,
+        bc_db: &BcV2DbRo<FileBackend>,
+        pubkey: PublicKey,
+    ) -> KvResult<Option<duniter_dbs::IdtyDbV2>> {
+        self.idty_(bc_db, pubkey)
+    }
+
+    fn unspent_uds_of_pubkey(
+        &self,
+        bc_db: &BcV2DbRo<FileBackend>,
+        pubkey: PublicKey,
+        page_info: PageInfo<BlockNumber>,
+        bn_to_exclude_opt: Option<BTreeSet<BlockNumber>>,
+        amount_target_opt: Option<SourceAmount>,
+    ) -> KvResult<PagedData<uds_of_pubkey::UdsWithSum>> {
+        self.unspent_uds_of_pubkey_(
+            bc_db,
+            pubkey,
+            page_info,
+            bn_to_exclude_opt.as_ref(),
+            amount_target_opt,
+        )
     }
 }
 
 #[cfg(test)]
-impl DbsReader {
+impl DbsReaderImpl {
     pub(crate) fn mem() -> Self {
         use duniter_gva_db::GvaV1DbWritable;
         let gva_db = duniter_gva_db::GvaV1Db::<Mem>::open(MemConf::default())
diff --git a/rust-libs/modules/gva/dbs-reader/src/txs_history.rs b/rust-libs/modules/gva/dbs-reader/src/txs_history.rs
index 240e7c7aa..3a4e3c52a 100644
--- a/rust-libs/modules/gva/dbs-reader/src/txs_history.rs
+++ b/rust-libs/modules/gva/dbs-reader/src/txs_history.rs
@@ -46,8 +46,8 @@ impl FromStr for TxBcCursor {
     }
 }
 
-impl DbsReader {
-    pub fn get_txs_history_bc_received(
+impl DbsReaderImpl {
+    pub(super) fn get_txs_history_bc_received_(
         &self,
         from: Option<u64>,
         page_info: PageInfo<TxBcCursor>,
@@ -192,7 +192,7 @@ impl DbsReader {
             )
         }
     }
-    pub fn get_txs_history_bc_sent(
+    pub(super) fn get_txs_history_bc_sent_(
         &self,
         from: Option<u64>,
         page_info: PageInfo<TxBcCursor>,
@@ -337,7 +337,7 @@ impl DbsReader {
             )
         }
     }
-    pub fn get_txs_history_mempool<TxsMpDb: TxsMpV2DbReadable>(
+    pub(super) fn get_txs_history_mempool_<TxsMpDb: 'static + TxsMpV2DbReadable>(
         &self,
         txs_mp_db_ro: &TxsMpDb,
         pubkey: PublicKey,
@@ -371,7 +371,7 @@ impl DbsReader {
 }
 
 fn txs_history_bc_collect<I: Iterator<Item = KvResult<GvaTxDbV1>>>(
-    dbs_reader: DbsReader,
+    dbs_reader: DbsReaderImpl,
     first_cursor_opt: Option<TxBcCursor>,
     first_hashs_opt: Option<SmallVec<[Hash; 8]>>,
     last_cursor_opt: Option<TxBcCursor>,
diff --git a/rust-libs/modules/gva/dbs-reader/src/uds_of_pubkey.rs b/rust-libs/modules/gva/dbs-reader/src/uds_of_pubkey.rs
index f94c77541..8ae09a58d 100644
--- a/rust-libs/modules/gva/dbs-reader/src/uds_of_pubkey.rs
+++ b/rust-libs/modules/gva/dbs-reader/src/uds_of_pubkey.rs
@@ -26,8 +26,8 @@ pub struct UdsWithSum {
     pub sum: SourceAmount,
 }
 
-impl DbsReader {
-    pub fn all_uds_of_pubkey(
+impl DbsReaderImpl {
+    pub(super) fn all_uds_of_pubkey_(
         &self,
         bc_db: &BcV2DbRo<FileBackend>,
         pubkey: PublicKey,
@@ -98,9 +98,9 @@ impl DbsReader {
             })
     }
 
-    pub fn unspent_uds_of_pubkey<BcDb: BcV2DbReadable>(
+    pub(super) fn unspent_uds_of_pubkey_(
         &self,
-        bc_db: &BcDb,
+        bc_db: &BcV2DbRo<FileBackend>,
         pubkey: PublicKey,
         page_info: PageInfo<BlockNumber>,
         bn_to_exclude_opt: Option<&BTreeSet<BlockNumber>>,
@@ -702,7 +702,8 @@ mod tests {
     fn test_unspent_uds_of_pubkey() -> KvResult<()> {
         let pk = PublicKey::default();
         let bc_db = duniter_dbs::databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?;
-        let dbs_reader = DbsReader::mem();
+        let bc_db_ro = bc_db.get_ro_handler();
+        let dbs_reader = DbsReaderImpl::mem();
 
         bc_db
             .uds_reval_write()
@@ -724,7 +725,7 @@ mod tests {
             data: UdsWithSum { uds, sum },
             has_previous_page,
             has_next_page,
-        } = dbs_reader.unspent_uds_of_pubkey(&bc_db, pk, PageInfo::default(), None, None)?;
+        } = dbs_reader.unspent_uds_of_pubkey(&bc_db_ro, pk, PageInfo::default(), None, None)?;
         assert_eq!(uds.len(), 7);
         assert_eq!(
             uds.first(),
@@ -744,7 +745,7 @@ mod tests {
             has_previous_page,
             has_next_page,
         } = dbs_reader.unspent_uds_of_pubkey(
-            &bc_db,
+            &bc_db_ro,
             pk,
             PageInfo {
                 pos: Some(BlockNumber(30)),
@@ -772,7 +773,7 @@ mod tests {
             has_previous_page,
             has_next_page,
         } = dbs_reader.unspent_uds_of_pubkey(
-            &bc_db,
+            &bc_db_ro,
             pk,
             PageInfo {
                 order: false,
@@ -800,7 +801,7 @@ mod tests {
             has_previous_page,
             has_next_page,
         } = dbs_reader.unspent_uds_of_pubkey(
-            &bc_db,
+            &bc_db_ro,
             pk,
             PageInfo {
                 pos: Some(BlockNumber(40)),
diff --git a/rust-libs/modules/gva/dbs-reader/src/utxos.rs b/rust-libs/modules/gva/dbs-reader/src/utxos.rs
index e6cdb05a3..2437507b6 100644
--- a/rust-libs/modules/gva/dbs-reader/src/utxos.rs
+++ b/rust-libs/modules/gva/dbs-reader/src/utxos.rs
@@ -73,8 +73,8 @@ pub struct UtxosWithSum {
     pub sum: SourceAmount,
 }
 
-impl DbsReader {
-    pub fn find_script_utxos<TxsMpDb: TxsMpV2DbReadable>(
+impl DbsReaderImpl {
+    pub(super) fn find_script_utxos_<TxsMpDb: 'static + TxsMpV2DbReadable>(
         &self,
         txs_mp_db_ro: &TxsMpDb,
         amount_target_opt: Option<SourceAmount>,
@@ -178,7 +178,7 @@ impl DbsReader {
             data: UtxosWithSum { utxos, sum },
         })
     }
-    pub fn first_scripts_utxos(
+    pub(super) fn first_scripts_utxos_(
         &self,
         first: usize,
         scripts: &[WalletScriptV10],
diff --git a/rust-libs/modules/gva/gql/Cargo.toml b/rust-libs/modules/gva/gql/Cargo.toml
index 34e20ea36..de7985e6a 100644
--- a/rust-libs/modules/gva/gql/Cargo.toml
+++ b/rust-libs/modules/gva/gql/Cargo.toml
@@ -27,7 +27,8 @@ serde = { version = "1.0.105", features = ["derive"] }
 
 [dev-dependencies]
 duniter-dbs = { path = "../../../duniter-dbs", features = ["mem"] }
-mockall = "0.8.0"
+duniter-gva-dbs-reader = { path = "../dbs-reader", features = ["mock"] }
+mockall = "0.9.1"
 serde_json = "1.0.53"
 tokio = { version = "1.2", features = ["macros", "rt-multi-thread", "time"] }
 unwrap = "1.2.1"
diff --git a/rust-libs/modules/gva/gql/src/lib.rs b/rust-libs/modules/gva/gql/src/lib.rs
index 059b7533c..37676ab87 100644
--- a/rust-libs/modules/gva/gql/src/lib.rs
+++ b/rust-libs/modules/gva/gql/src/lib.rs
@@ -48,7 +48,7 @@ use crate::inputs_validators::TxCommentValidator;
 use crate::pagination::Pagination;
 use crate::scalars::{PkOrScriptGva, PubKeyGva};
 #[cfg(test)]
-use crate::tests::DbsReader;
+use crate::tests::DbsReaderImpl;
 use async_graphql::connection::{Connection, Edge, EmptyFields};
 use async_graphql::validators::{IntGreaterThan, IntRange, ListMaxLength, ListMinLength};
 use dubp::common::crypto::keys::{ed25519::PublicKey, PublicKey as _};
@@ -62,8 +62,9 @@ use duniter_dbs::databases::txs_mp_v2::TxsMpV2DbReadable;
 use duniter_dbs::prelude::*;
 use duniter_dbs::{kv_typed::prelude::*, FileBackend};
 use duniter_gva_dbs_reader::pagination::PageInfo;
-#[cfg(not(test))]
 use duniter_gva_dbs_reader::DbsReader;
+#[cfg(not(test))]
+use duniter_gva_dbs_reader::DbsReaderImpl;
 use duniter_mempools::TxsMempool;
 use futures::{Stream, StreamExt};
 use resiter::map::Map;
@@ -83,102 +84,12 @@ pub struct ServerMetaData {
 
 #[cfg(test)]
 mod tests {
+    pub use duniter_gva_dbs_reader::MockDbsReader;
+
     use super::*;
-    use dubp::{block::DubpBlockV10, documents::transaction::TransactionInputV10};
-    use duniter_dbs::{
-        databases::{bc_v2::*, cm_v1::CmV1DbReadable},
-        BlockMetaV2, IdtyDbV2, SourceAmountValV2,
-    };
-    use duniter_gva_dbs_reader::pagination::*;
     use fast_threadpool::ThreadPoolConfig;
-    use std::collections::VecDeque;
 
-    mockall::mock! {
-        pub DbsReader {
-            fn all_uds_of_pubkey(
-                &self,
-                bc_db: &BcV2DbRo<FileBackend>,
-                pubkey: PublicKey,
-                page_info: PageInfo<BlockNumber>,
-            ) -> KvResult<PagedData<duniter_gva_dbs_reader::uds_of_pubkey::UdsWithSum>>;
-            fn block(&self, bc_db: &BcV2DbRo<FileBackend>, number: U32BE) -> KvResult<Option<BlockMetaV2>>;
-            fn blocks(&self, bc_db: &BcV2DbRo<FileBackend>, page_info: PageInfo<duniter_gva_dbs_reader::block::BlockCursor>) -> KvResult<PagedData<Vec<(duniter_gva_dbs_reader::block::BlockCursor, BlockMetaV2)>>>;
-            fn find_inputs<BcDb: 'static + BcV2DbReadable, TxsMpDb: 'static + TxsMpV2DbReadable>(
-                &self,
-                bc_db: &BcDb,
-                txs_mp_db: &TxsMpDb,
-                amount: SourceAmount,
-                script: &WalletScriptV10,
-                use_mempool_sources: bool,
-            ) -> anyhow::Result<(Vec<TransactionInputV10>, SourceAmount)>;
-            fn find_script_utxos<TxsMpDb: 'static + TxsMpV2DbReadable>(
-                &self,
-                txs_mp_db_ro: &TxsMpDb,
-                amount_target_opt: Option<SourceAmount>,
-                page_info: PageInfo<duniter_gva_dbs_reader::utxos::UtxoCursor>,
-                script: &WalletScriptV10,
-            ) -> anyhow::Result<PagedData<duniter_gva_dbs_reader::utxos::UtxosWithSum>>;
-            fn first_scripts_utxos(
-                &self,
-                first: usize,
-                scripts: &[WalletScriptV10],
-            ) -> anyhow::Result<Vec<arrayvec::ArrayVec<[duniter_gva_dbs_reader::utxos::Utxo; duniter_gva_dbs_reader::utxos::MAX_FIRST_UTXOS]>>>;
-            fn get_account_balance(
-                &self,
-                account_script: &WalletScriptV10,
-            ) -> KvResult<Option<SourceAmountValV2>>;
-            fn get_blockchain_time(
-                &self,
-                block_number: BlockNumber,
-            ) -> anyhow::Result<u64>;
-            fn get_current_block<CmDb: 'static + CmV1DbReadable>(
-                &self,
-                cm_db: &CmDb,
-            ) -> KvResult<Option<DubpBlockV10>>;
-            fn get_current_block_meta<CmDb: 'static + CmV1DbReadable>(
-                &self,
-                cm_db: &CmDb,
-            ) -> KvResult<Option<BlockMetaV2>>;
-            fn get_current_frame<BcDb: 'static + BcV2DbReadable, CmDb: 'static + CmV1DbReadable>(
-                &self,
-                bc_db: &BcDb,
-                cm_db: &CmDb,
-            ) -> anyhow::Result<Vec<duniter_dbs::BlockMetaV2>>;
-            fn get_current_ud<BcDb: 'static + BcV2DbReadable>(
-                &self,
-                bc_db: &BcDb,
-            ) -> KvResult<Option<SourceAmount>>;
-            fn get_txs_history_bc_received(
-                &self,
-                from: Option<u64>,
-                page_info: PageInfo<duniter_gva_dbs_reader::txs_history::TxBcCursor>,
-                script_hash: Hash,
-                to: Option<u64>,
-            ) -> KvResult<PagedData<VecDeque<duniter_gva_db::GvaTxDbV1>>>;
-            fn get_txs_history_bc_sent(
-                &self,
-                from: Option<u64>,
-                page_info: PageInfo<duniter_gva_dbs_reader::txs_history::TxBcCursor>,
-                script_hash: Hash,
-                to: Option<u64>,
-            ) -> KvResult<PagedData<VecDeque<duniter_gva_db::GvaTxDbV1>>>;
-            fn get_txs_history_mempool<TxsMpDb: 'static + TxsMpV2DbReadable>(
-                &self,
-                txs_mp_db_ro: &TxsMpDb,
-                pubkey: PublicKey,
-            ) -> KvResult<(Vec<TransactionDocumentV10>, Vec<TransactionDocumentV10>)>;
-            fn idty(&self, bc_db: &BcV2DbRo<FileBackend>, pubkey: PublicKey) -> KvResult<Option<IdtyDbV2>>;
-            fn unspent_uds_of_pubkey<BcDb: 'static + BcV2DbReadable>(
-                &self,
-                bc_db: &BcDb,
-                pubkey: PublicKey,
-                page_info: PageInfo<BlockNumber>,
-                bn_to_exclude_opt: Option<&'static std::collections::BTreeSet<BlockNumber>>,
-                amount_target_opt: Option<SourceAmount>,
-            ) -> KvResult<PagedData<duniter_gva_dbs_reader::uds_of_pubkey::UdsWithSum>>;
-        }
-    }
-    pub type DbsReader = duniter_dbs::kv_typed::prelude::Arc<MockDbsReader>;
+    pub type DbsReaderImpl = duniter_dbs::kv_typed::prelude::Arc<MockDbsReader>;
 
     pub(crate) fn create_schema(dbs_ops: MockDbsReader) -> KvResult<GvaSchema> {
         let dbs = SharedDbs::mem()?;
diff --git a/rust-libs/modules/gva/gql/src/schema.rs b/rust-libs/modules/gva/gql/src/schema.rs
index e56dac9fb..6ef5830de 100644
--- a/rust-libs/modules/gva/gql/src/schema.rs
+++ b/rust-libs/modules/gva/gql/src/schema.rs
@@ -46,7 +46,7 @@ pub fn build_schema_with_data(data: GvaSchemaData, logger: bool) -> GvaSchema {
 
 pub struct GvaSchemaData {
     pub dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>,
-    pub dbs_reader: DbsReader,
+    pub dbs_reader: DbsReaderImpl,
     pub server_meta_data: ServerMetaData,
     pub txs_mempool: TxsMempool,
 }
@@ -54,13 +54,13 @@ pub struct GvaSchemaData {
 #[cfg(not(test))]
 impl GvaSchemaData {
     #[inline(always)]
-    pub fn dbs_reader(&self) -> DbsReader {
+    pub fn dbs_reader(&self) -> DbsReaderImpl {
         self.dbs_reader
     }
 }
 #[cfg(test)]
 impl GvaSchemaData {
-    pub fn dbs_reader(&self) -> DbsReader {
+    pub fn dbs_reader(&self) -> DbsReaderImpl {
         self.dbs_reader.clone()
     }
 }
diff --git a/rust-libs/tools/kv_typed/Cargo.toml b/rust-libs/tools/kv_typed/Cargo.toml
index 0761bbb51..65554446b 100644
--- a/rust-libs/tools/kv_typed/Cargo.toml
+++ b/rust-libs/tools/kv_typed/Cargo.toml
@@ -17,7 +17,7 @@ cfg-if = "0.1.10"
 flume = "0.10.0"
 leveldb_minimal = { version = "0.1.0", optional = true }
 lmdb-zero = { version = "0.4.4", optional = true }
-mockall = { version = "0.8.0", optional = true }
+mockall = { version = "0.9.1", optional = true }
 parking_lot = "0.11.0"
 paste = "1.0.2"
 rayon = { version = "1.3.1", optional = true }
-- 
GitLab