diff --git a/Cargo.lock b/Cargo.lock index 78d354aaf1a73f5b27113cf23af82c7e1ca5859f..858903e22f2d0276c99221cc59f0d650b2ba5d6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1069,6 +1069,7 @@ dependencies = [ "dubp", "duniter-dbs", "duniter-dbs-write-ops", + "duniter-gva", "duniter-gva-db-writer", "fast-threadpool", "rayon", @@ -1192,7 +1193,6 @@ dependencies = [ "duniter-dbs", "duniter-dbs-read-ops", "duniter-dbs-write-ops", - "duniter-gva", "duniter-mempools", "duniter-module", "duniter-server", @@ -1260,7 +1260,6 @@ dependencies = [ "duniter-dbs-read-ops", "duniter-dbs-write-ops", "duniter-gva", - "duniter-gva-dbs-reader", "duniter-mempools", "duniter-module", "fast-threadpool", diff --git a/neon/native/src/server.rs b/neon/native/src/server.rs index 70a46f68d8ab7f64ce5414150ff6756e04a6cb20..d1804c53fe75b7ea30397839c74ddab058208d38 100644 --- a/neon/native/src/server.rs +++ b/neon/native/src/server.rs @@ -21,7 +21,7 @@ use dubp::documents::{ }; use dubp::documents_parser::prelude::*; use dubp::{common::crypto::hashs::Hash, crypto::keys::ed25519::Ed25519KeyPair}; -use duniter_server::{DuniterConf, DuniterServer, GvaConf, PeerCardStringified}; +use duniter_server::{DuniterConf, DuniterServer, GvaConf}; use neon::declare_types; use neon::prelude::*; use serde::{Deserialize, Serialize}; @@ -60,7 +60,7 @@ declare_types! { .downcast::<JsString>() .or_throw(&mut cx)? .value(); - if std::env::var_os("DUNITER_MEMORY_ONLY") == Some("yes".into()) { + if std::env::var_os("DUNITER_JS_TESTS") == Some("yes".into()) { None } else { Some(PathBuf::from(home_path_str)) @@ -265,11 +265,11 @@ declare_types! { Ok(txs_history) => { let sent: Vec<_> = txs_history.sent .into_iter() - .map(|db_tx| DbTx::v10(db_tx.tx.to_string_object(), db_tx.tx.get_hash(), db_tx.written_block.number.0, db_tx.written_time)) + .map(|(tx, wb, wt)| DbTx::v10(tx.to_string_object(), tx.get_hash(), wb.number.0, wt)) .collect(); let received: Vec<_> = txs_history.received .into_iter() - .map(|db_tx| DbTx::v10(db_tx.tx.to_string_object(), db_tx.tx.get_hash(), db_tx.written_block.number.0, db_tx.written_time)) + .map(|(tx, wb, wt)| DbTx::v10(tx.to_string_object(), tx.get_hash(), wb.number.0, wt)) .collect(); let sending: Vec<_> = txs_history.sending.into_iter().map(|tx| tx.to_string_object()).collect(); let pending: Vec<_> = txs_history.pending.into_iter().map(|tx| tx.to_string_object()).collect(); @@ -354,12 +354,21 @@ declare_types! { let peer_js = cx.argument::<JsValue>(0)?; let peer_stringified: PeerCardStringified = neon_serde::from_value(&mut cx, peer_js)?; + let peer = duniter_server::PeerCardDbV1 { + version: peer_stringified.version, + currency: peer_stringified.currency, + pubkey: peer_stringified.pubkey, + blockstamp: peer_stringified.blockstamp, + endpoints: peer_stringified.endpoints, + status: peer_stringified.status, + signature: peer_stringified.signature, + }; let this = cx.this(); let res = { let guard = cx.lock(); let server = this.borrow(&guard); - server.server.save_peer(peer_stringified) + server.server.save_peer(peer) }.map(|()| cx.undefined().upcast()); into_neon_res(&mut cx, res) } @@ -367,12 +376,21 @@ declare_types! { let peer_js = cx.argument::<JsValue>(0)?; let peer_stringified: PeerCardStringified = neon_serde::from_value(&mut cx, peer_js)?; + let peer = duniter_server::PeerCardDbV1 { + version: peer_stringified.version, + currency: peer_stringified.currency, + pubkey: peer_stringified.pubkey, + blockstamp: peer_stringified.blockstamp, + endpoints: peer_stringified.endpoints, + status: peer_stringified.status, + signature: peer_stringified.signature, + }; let this = cx.this(); { let guard = cx.lock(); let server = this.borrow(&guard); - server.server.update_self_peer(peer_stringified) + server.server.update_self_peer(peer) }; Ok(cx.undefined().upcast()) } @@ -430,6 +448,18 @@ struct HeadWS2Pv1ConfStringified { step: Option<usize>, } +#[derive(Clone, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "camelCase")] +pub struct PeerCardStringified { + pub version: u32, + pub currency: String, + pub pubkey: String, + pub blockstamp: String, + pub endpoints: Vec<String>, + pub status: String, + pub signature: String, +} + #[derive(Deserialize, Serialize)] #[serde(rename_all = "camelCase")] struct RustServerConfStringified { diff --git a/package.json b/package.json index 278ff64a2ee384de76530478a3c5ac12c2e586cc..2d36f39908cc120a725a48bb247d1037f4530548 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "tsc": "tsc", "tscw": "tsc -w", "doc": "typedoc --out typedoc/ index.ts app/ --mode file --readme README.md --includeDeclarations --sourcefile-url-prefix \"https://git.duniter.org/nodes/typescript/duniter/blob/loki/\"", - "test": "DUNITER_MEMORY_ONLY=yes DUNITER_LOG_STDOUT=no nyc --reporter html mocha", + "test": "DUNITER_JS_TESTS=yes DUNITER_LOG_STDOUT=no nyc --reporter html mocha", "start": "cargo run -- start", "build": "./neon/build.sh && cd.. && tsc && cd \"../node_modules/duniter-ui\" && npm install && npm run build", "install": "./neon/build.sh", diff --git a/rust-bins/duniter-dbex/Cargo.toml b/rust-bins/duniter-dbex/Cargo.toml index 1413631fd3c775b35edd0e707a5fa4165a15c746..4ca70ed24751d9afb73d678624bb5451ea6e0731 100644 --- a/rust-bins/duniter-dbex/Cargo.toml +++ b/rust-bins/duniter-dbex/Cargo.toml @@ -25,6 +25,7 @@ dirs = "3.0.1" dubp = { version = "0.32.3" } duniter-dbs = { path = "../../rust-libs/duniter-dbs", default-features = false, features = ["explorer", "leveldb_backend", "sled_backend"] } duniter-dbs-write-ops = { path = "../../rust-libs/duniter-dbs-write-ops", default-features = false, features = ["explorer", "leveldb_backend", "sled_backend"] } +duniter-gva = { path = "../../rust-libs/modules/gva" } duniter-gva-db-writer = { path = "../../rust-libs/modules/gva/db-writer" } fast-threadpool = "0.2.2" rayon = "1.3.1" diff --git a/rust-bins/duniter-dbex/src/migrate.rs b/rust-bins/duniter-dbex/src/migrate.rs index b04f307825a438dbd6ffccc1c156d9c832d958cd..aba30ba3c6db70e20d8b704fa1d77bb02a29b0c0 100644 --- a/rust-bins/duniter-dbex/src/migrate.rs +++ b/rust-bins/duniter-dbex/src/migrate.rs @@ -26,16 +26,17 @@ const CHUNK_SIZE: usize = 250; pub(crate) fn migrate(profile_path: PathBuf) -> anyhow::Result<()> { let start_time = Instant::now(); - let (bc_db, dbs) = duniter_dbs::open_dbs(Some(profile_path.as_path())); + let (bc_db, shared_dbs) = duniter_dbs::open_dbs(Some(profile_path.as_path())); + let gva_db = duniter_gva::GvaModule::get_gva_db_rw(Some(profile_path.as_path())); // Clear bc_db and gva_db bc_db.clear()?; - dbs.gva_db.clear()?; + gva_db.clear()?; - if let Err(e) = migrate_inner(&bc_db, dbs.clone(), profile_path, start_time) { + if let Err(e) = migrate_inner(&bc_db, gva_db, profile_path, shared_dbs, start_time) { // Clear bc_db and gva_db bc_db.clear()?; - dbs.gva_db.clear()?; + gva_db.clear()?; Err(e) } else { @@ -45,8 +46,9 @@ pub(crate) fn migrate(profile_path: PathBuf) -> anyhow::Result<()> { fn migrate_inner( bc_db: &BcV2Db<FileBackend>, - dbs: DuniterDbs<FileBackend>, + gva_db: &'static GvaV1Db<FileBackend>, profile_path: PathBuf, + shared_dbs: SharedDbs<FileBackend>, start_time: Instant, ) -> anyhow::Result<()> { let data_path = profile_path.join(crate::DATA_DIR); @@ -55,15 +57,10 @@ fn migrate_inner( ..Default::default() })?; - let dbs_pool = ThreadPool::start(ThreadPoolConfig::default(), dbs).into_sync_handler(); + let dbs_pool = ThreadPool::start(ThreadPoolConfig::default(), shared_dbs).into_sync_handler(); if let Some(target) = get_target_block_number(&duniter_js_db)? { println!("target block: #{}", target.0); - /*let chunk_count = if (target.0 as usize + 1) % CHUNK_SIZE == 0 { - (target.0 as usize + 1) / CHUNK_SIZE - } else { - (target.0 as usize / CHUNK_SIZE) + 1 - };*/ let (s, r) = std::sync::mpsc::channel(); let reader_handle = std::thread::spawn(move || { @@ -114,9 +111,9 @@ fn migrate_inner( let chunk = Arc::from(chunk); let chunk_arc_clone = Arc::clone(&chunk); let gva_handle = dbs_pool - .launch(move |dbs| { + .launch(move |_| { for block in chunk_arc_clone.deref() { - duniter_gva_db_writer::apply_block(block, &dbs.gva_db)?; + duniter_gva_db_writer::apply_block(block, gva_db)?; } Ok::<_, KvError>(()) }) @@ -135,10 +132,7 @@ fn migrate_inner( println!("Flush DBs caches on disk..."); bc_db.save()?; - dbs_pool.execute(|dbs| { - dbs.gva_db.save()?; - Ok::<(), KvError>(()) - })??; + gva_db.save()?; if let Some(current) = current { if current.number != target.0 { diff --git a/rust-libs/duniter-dbs-write-ops/src/apply_block.rs b/rust-libs/duniter-dbs-write-ops/src/apply_block.rs index 756d07b81cf83972d133d39feb4d87e0af5fbd06..12ba380fc4f27fa317357d98cb8e302787db5e6f 100644 --- a/rust-libs/duniter-dbs-write-ops/src/apply_block.rs +++ b/rust-libs/duniter-dbs-write-ops/src/apply_block.rs @@ -19,7 +19,7 @@ pub fn apply_block( bc_db: &BcV2Db<FileBackend>, block: Arc<DubpBlockV10>, current_opt: Option<BlockMetaV2>, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, throw_chainability: bool, ) -> KvResult<BlockMetaV2> { if let Some(current) = current_opt { @@ -50,7 +50,7 @@ pub fn apply_block( pub fn apply_chunk( bc_db: &BcV2Db<FileBackend>, current_opt: Option<BlockMetaV2>, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, blocks: Arc<[DubpBlockV10]>, ) -> KvResult<BlockMetaV2> { verify_chunk_chainability(current_opt, &blocks)?; @@ -103,7 +103,7 @@ fn verify_chunk_chainability( fn apply_block_inner( bc_db: &BcV2Db<FileBackend>, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, block: Arc<DubpBlockV10>, ) -> KvResult<BlockMetaV2> { let block_arc_clone = Arc::clone(&block); @@ -126,7 +126,7 @@ fn apply_block_inner( fn apply_chunk_inner( bc_db: &BcV2Db<FileBackend>, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, blocks: Arc<[DubpBlockV10]>, ) -> KvResult<BlockMetaV2> { let blocks_len = blocks.len(); diff --git a/rust-libs/duniter-dbs-write-ops/src/lib.rs b/rust-libs/duniter-dbs-write-ops/src/lib.rs index 607d90124538da8673bd820c0d97659394e377cd..405a35a899dba4cabf3acff6d3d80e22a1528e4b 100644 --- a/rust-libs/duniter-dbs-write-ops/src/lib.rs +++ b/rust-libs/duniter-dbs-write-ops/src/lib.rs @@ -42,7 +42,7 @@ use duniter_dbs::{ txs_mp_v2::{TxsMpV2Db, TxsMpV2DbReadable, TxsMpV2DbWritable}, }, kv_typed::prelude::*, - BlockMetaV2, DuniterDbs, FileBackend, HashKeyV2, PendingTxDbV2, PubKeyKeyV2, PubKeyValV2, + BlockMetaV2, FileBackend, HashKeyV2, PendingTxDbV2, PubKeyKeyV2, PubKeyValV2, SharedDbs, SourceAmountValV2, UtxoValV2, WalletConditionsV2, }; use resiter::filter_map::FilterMap; diff --git a/rust-libs/duniter-dbs/src/lib.rs b/rust-libs/duniter-dbs/src/lib.rs index ade5c98f01b25029c755c29234e72584b2f4ac1f..6ac199e37260abd7cf6d6099fd38ef15b8930f90 100644 --- a/rust-libs/duniter-dbs/src/lib.rs +++ b/rust-libs/duniter-dbs/src/lib.rs @@ -41,7 +41,7 @@ pub use kv_typed; // Prelude pub mod prelude { pub use crate::open_dbs::BackendConf; - pub use crate::DuniterDbs; + pub use crate::SharedDbs; #[cfg(feature = "explorer")] pub use kv_typed::explorer::{ DbExplorable, EntryFound, ExplorerAction, ExplorerActionResponse, ValueCaptures, @@ -116,26 +116,23 @@ pub type FileBackend = kv_typed::backend::sled::Sled; pub type FileBackend = kv_typed::backend::memory::Mem; #[derive(Clone, Debug)] -pub struct DuniterDbs<B: Backend> { +pub struct SharedDbs<B: Backend> { pub bc_db_ro: databases::bc_v2::BcV2DbRo<B>, 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>, } -impl DuniterDbs<Mem> { +impl SharedDbs<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 { + Ok(SharedDbs { bc_db_ro: databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?.get_ro_handler(), 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 cc07815fa189743f6d7992b45f7f91ad5605f5b2..04ae6264a4cf3aaffb28bfe9a4e91dc2a3e48610 100644 --- a/rust-libs/duniter-dbs/src/open_dbs.rs +++ b/rust-libs/duniter-dbs/src/open_dbs.rs @@ -16,35 +16,29 @@ 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::*; pub fn open_dbs<B: BackendConf>( - home_path_opt: Option<&Path>, -) -> (crate::databases::bc_v2::BcV2Db<B>, DuniterDbs<B>) { + profile_path_opt: Option<&Path>, +) -> (crate::databases::bc_v2::BcV2Db<B>, SharedDbs<B>) { let bc_db = crate::databases::bc_v2::BcV2Db::<B>::open(B::gen_backend_conf( crate::databases::bc_v2::BcV2Db::<B>::NAME, - home_path_opt, + profile_path_opt, )) .expect("fail to open BcV2 DB"); - let dbs = DuniterDbs { + let dbs = SharedDbs { bc_db_ro: bc_db.get_ro_handler(), 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( - crate::databases::dunp_v1::DunpV1Db::<B>::NAME, - home_path_opt, + "dunp_v1", + profile_path_opt, )) .expect("fail to open Dunp DB"), - gva_db: crate::databases::gva_v1::GvaV1Db::<B>::open(B::gen_backend_conf( - crate::databases::gva_v1::GvaV1Db::<B>::NAME, - home_path_opt, - )) - .expect("fail to open Gva DB"), txs_mp_db: crate::databases::txs_mp_v2::TxsMpV2Db::<B>::open(B::gen_backend_conf( crate::databases::txs_mp_v2::TxsMpV2Db::<B>::NAME, - home_path_opt, + profile_path_opt, )) .expect("fail to open TxsMp DB"), }; @@ -54,22 +48,22 @@ pub fn open_dbs<B: BackendConf>( pub trait BackendConf: Backend { fn gen_backend_conf( db_name: &'static str, - home_path_opt: Option<&Path>, + profile_path_opt: Option<&Path>, ) -> <Self as Backend>::Conf; } impl BackendConf for Mem { #[inline(always)] - fn gen_backend_conf(_db_name: &'static str, _home_path_opt: Option<&Path>) -> MemConf { + fn gen_backend_conf(_db_name: &'static str, _profile_path_opt: Option<&Path>) -> MemConf { MemConf::default() } } /*impl BackendConf for Lmdb { #[inline(always)] - fn gen_backend_conf(db_name: &'static str, home_path_opt: Option<&Path>) -> LmdbConf { + fn gen_backend_conf(db_name: &'static str, profile_path_opt: Option<&Path>) -> LmdbConf { let conf = LmdbConf::default(); - if let Some(data_path) = home_path_opt { + if let Some(data_path) = profile_path_opt { conf.folder_path(data_path.join(format!("data/{}_lmdb", db_name))) } else { let random = rand::random::<u128>(); @@ -84,7 +78,7 @@ impl BackendConf for Mem { impl BackendConf for Sled { #[inline(always)] - fn gen_backend_conf(db_name: &'static str, home_path_opt: Option<&Path>) -> SledConf { + fn gen_backend_conf(db_name: &'static str, profile_path_opt: Option<&Path>) -> SledConf { let mut conf = SledConf::default().flush_every_ms(Some(10_000)); conf = match db_name { "bc_v2" => { @@ -109,7 +103,7 @@ impl BackendConf for Sled { } _ => conf.use_compression(false), }; - if let Some(data_path) = home_path_opt { + if let Some(data_path) = profile_path_opt { conf.path(data_path.join(format!("data/{}_sled", db_name))) } else { conf.temporary(true) diff --git a/rust-libs/duniter-module/src/lib.rs b/rust-libs/duniter-module/src/lib.rs index bc804f974535c55b21c40a3531fcdf147cd63a56..fbd440c2aa557f95a5fe66577a9b46a3e78dd636 100644 --- a/rust-libs/duniter-module/src/lib.rs +++ b/rust-libs/duniter-module/src/lib.rs @@ -22,9 +22,14 @@ unused_import_braces )] -use dubp::block::DubpBlockV10; +use dubp::{ + block::DubpBlockV10, + common::prelude::{BlockNumber, Blockstamp}, + crypto::{hashs::Hash, keys::ed25519::PublicKey}, + documents::transaction::TransactionDocumentV10, +}; use duniter_conf::DuniterConf; -use duniter_dbs::{kv_typed::prelude::*, DuniterDbs, FileBackend}; +use duniter_dbs::{kv_typed::prelude::*, FileBackend, SharedDbs}; use duniter_mempools::Mempools; use fast_threadpool::{JoinHandle, ThreadPoolDisconnected}; use std::path::Path; @@ -38,7 +43,7 @@ pub trait DuniterModule: 'static + Sized { fn apply_block( _block: Arc<DubpBlockV10>, _conf: &duniter_conf::DuniterConf, - _dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + _dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, _profile_path_opt: Option<&Path>, ) -> Result<Option<JoinHandle<KvResult<()>>>, ThreadPoolDisconnected> { Ok(None) @@ -47,7 +52,7 @@ pub trait DuniterModule: 'static + Sized { fn apply_chunk_of_blocks( _blocks: Arc<[DubpBlockV10]>, _conf: &duniter_conf::DuniterConf, - _dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + _dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, _profile_path_opt: Option<&Path>, ) -> Result<Option<JoinHandle<KvResult<()>>>, ThreadPoolDisconnected> { Ok(None) @@ -56,7 +61,7 @@ pub trait DuniterModule: 'static + Sized { fn revert_block( _block: Arc<DubpBlockV10>, _conf: &duniter_conf::DuniterConf, - _dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + _dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, _profile_path_opt: Option<&Path>, ) -> Result<Option<JoinHandle<KvResult<()>>>, ThreadPoolDisconnected> { Ok(None) @@ -65,25 +70,54 @@ pub trait DuniterModule: 'static + Sized { fn init( conf: &DuniterConf, currency: &str, - dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, + dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, mempools: Mempools, profile_path_opt: Option<&Path>, software_version: &'static str, ) -> anyhow::Result<(Self, Vec<Endpoint>)>; async fn start(self) -> anyhow::Result<()>; + + // Needed for BMA only, will be removed when the migration is complete. + #[doc(hidden)] + fn get_transactions_history_for_bma( + _dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, + _profile_path_opt: Option<&Path>, + _pubkey: PublicKey, + ) -> KvResult<Option<TxsHistoryForBma>> { + Ok(None) + } + // Needed for BMA only, will be removed when the migration is complete. + #[doc(hidden)] + fn get_tx_by_hash( + _dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, + _hash: Hash, + _profile_path_opt: Option<&Path>, + ) -> KvResult<Option<(TransactionDocumentV10, Option<BlockNumber>)>> { + Ok(None) + } +} + +// Needed for BMA only, will be removed when the migration is complete. +#[doc(hidden)] +#[derive(Default)] +pub struct TxsHistoryForBma { + pub sent: Vec<(TransactionDocumentV10, Blockstamp, i64)>, + pub received: Vec<(TransactionDocumentV10, Blockstamp, i64)>, + pub sending: Vec<TransactionDocumentV10>, + pub pending: Vec<TransactionDocumentV10>, } #[macro_export] macro_rules! plug_duniter_modules { - ([$($M:ty),*]) => { + ([$($M:ty),*], $TxsHistoryForBma:ident) => { paste::paste! { use anyhow::Context as _; #[allow(dead_code)] fn apply_block_modules( block: Arc<DubpBlockV10>, conf: &duniter_conf::DuniterConf, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, profile_path_opt: Option<&Path>, ) -> KvResult<()> { $( @@ -100,7 +134,7 @@ macro_rules! plug_duniter_modules { fn apply_chunk_of_blocks_modules( blocks: Arc<[DubpBlockV10]>, conf: &duniter_conf::DuniterConf, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, profile_path_opt: Option<&Path>, ) -> KvResult<()> { $( @@ -117,7 +151,7 @@ macro_rules! plug_duniter_modules { fn revert_block_modules( block: Arc<DubpBlockV10>, conf: &duniter_conf::DuniterConf, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, profile_path_opt: Option<&Path>, ) -> KvResult<()> { $( @@ -133,7 +167,7 @@ macro_rules! plug_duniter_modules { async fn start_duniter_modules( conf: &DuniterConf, currency: String, - dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, + dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, mempools: duniter_mempools::Mempools, profile_path_opt: Option<std::path::PathBuf>, software_version: &'static str, @@ -171,6 +205,37 @@ macro_rules! plug_duniter_modules { Ok(()) } + + // Needed for BMA only, will be removed when the migration is complete. + #[allow(dead_code)] + #[doc(hidden)] + fn get_transactions_history_for_bma( + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, + profile_path_opt: Option<&Path>, + pubkey: PublicKey, + ) -> KvResult<TxsHistoryForBma> { + $( + if let Some(txs_history) = <$M>::get_transactions_history_for_bma(dbs_pool, profile_path_opt, pubkey)? { + return Ok(txs_history); + } + )* + Ok(TxsHistoryForBma::default()) + } + // Needed for BMA only, will be removed when the migration is complete. + #[allow(dead_code)] + #[doc(hidden)] + fn get_tx_by_hash( + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, + hash: Hash, + profile_path_opt: Option<&Path>, + ) -> KvResult<Option<(TransactionDocumentV10, Option<BlockNumber>)>> { + $( + if let Some(tx_with_wb) = <$M>::get_tx_by_hash(dbs_pool, hash, profile_path_opt)? { + return Ok(Some(tx_with_wb)); + } + )* + Ok(None) + } } }; } @@ -187,7 +252,7 @@ mod tests { fn init( _conf: &DuniterConf, _currency: &str, - _dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, + _dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, _mempools: Mempools, profile_path_opt: Option<&Path>, _software_version: &'static str, @@ -210,7 +275,7 @@ mod tests { fn init( _conf: &DuniterConf, _currency: &str, - _dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, + _dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, _mempools: Mempools, _profile_path_opt: Option<&Path>, _software_version: &'static str, @@ -225,9 +290,9 @@ mod tests { #[tokio::test] async fn test_macro_plug_duniter_modules() -> anyhow::Result<()> { - plug_duniter_modules!([TestMod1, TestMod2]); + plug_duniter_modules!([TestMod1, TestMod2], TxsHistoryForBma); - let dbs = DuniterDbs::mem()?; + let dbs = SharedDbs::mem()?; let threadpool = fast_threadpool::ThreadPool::start(fast_threadpool::ThreadPoolConfig::default(), dbs); diff --git a/rust-libs/duniter-server/Cargo.toml b/rust-libs/duniter-server/Cargo.toml index f3e120d72cd16e335e12c0649323463c9e85a255..6a608039f0ea2c3ef7189a408a949910e9b17113 100644 --- a/rust-libs/duniter-server/Cargo.toml +++ b/rust-libs/duniter-server/Cargo.toml @@ -13,8 +13,7 @@ duniter-conf = { path = "../duniter-conf" } duniter-dbs = { path = "../duniter-dbs" } duniter-dbs-read-ops = { path = "../duniter-dbs-read-ops" } duniter-dbs-write-ops = { path = "../duniter-dbs-write-ops" } -duniter-gva = { path = "../modules/gva" } -duniter-gva-dbs-reader = { path = "../modules/gva/dbs-reader" } +duniter-gva = { path = "../modules/gva", optional = true } duniter-mempools = { path = "../duniter-mempools" } duniter-module = { path = "../duniter-module" } fast-threadpool = "0.2.2" @@ -24,5 +23,10 @@ paste = "1.0.2" resiter = "0.4.0" tokio = { version = "0.2.22", features = ["io-util", "rt-threaded"] } +[features] +default = ["gva"] + +gva = ["duniter-gva"] + [dev-dependencies] duniter-dbs = { path = "../duniter-dbs", features = ["mem"] } diff --git a/rust-libs/duniter-server/src/legacy/dunp.rs b/rust-libs/duniter-server/src/legacy/dunp.rs index 020e32e708c84dab381d57739c0bee5f08a88ec8..44c9552e3c9b889856b951b650dacfa15b8ec56e 100644 --- a/rust-libs/duniter-server/src/legacy/dunp.rs +++ b/rust-libs/duniter-server/src/legacy/dunp.rs @@ -43,7 +43,7 @@ impl DuniterServer { .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<()> { + pub fn save_peer(&self, new_peer_card: PeerCardDbV1) -> 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 _; @@ -65,23 +65,12 @@ impl DuniterServer { .expect("dbs pool disconnected") .map_err(|e| e.into()) } - pub fn update_self_peer(&self, new_peer_card: PeerCardStringified) { + pub fn update_self_peer(&self, new_peer_card: PeerCardDbV1) { self.dbs_pool .execute(move |dbs| { dbs.cm_db .self_peer_old_write() - .upsert( - (), - 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, - }, - ) + .upsert((), new_peer_card) .expect("fail to write on memory db") }) .expect("dbs pool disconnected") @@ -131,7 +120,7 @@ mod tests { use duniter_dbs::databases::dunp_v1::DunpV1DbReadable as _; let (server, dbs) = DuniterServer::test(DuniterConf::default())?; - let peer = PeerCardStringified { + let peer = PeerCardDbV1 { version: 0, currency: "test".to_owned(), pubkey: "82NdD9eEbXSjRJXeJdqf56xkpu6taTfTeEqtAtmtbyXY".to_owned(), @@ -148,18 +137,7 @@ mod tests { assert_eq!(dbs.dunp_db.peers_old().count()?, 1); let peer_db = dbs.dunp_db.peers_old().get(&PubKeyKeyV2(pubkey))?; - assert_eq!( - peer_db, - Some(PeerCardDbV1 { - version: peer.version, - currency: peer.currency, - pubkey: peer.pubkey, - blockstamp: peer.blockstamp, - endpoints: peer.endpoints, - status: peer.status, - signature: peer.signature, - }) - ); + assert_eq!(peer_db, Some(peer)); Ok(()) } diff --git a/rust-libs/duniter-server/src/legacy/tx_history.rs b/rust-libs/duniter-server/src/legacy/tx_history.rs index 4c55b2fc03f01f495b4af5edffe09b5fc0fcc631..e06cf4445bde9a1f3816fa09b873803fe8a2aead 100644 --- a/rust-libs/duniter-server/src/legacy/tx_history.rs +++ b/rust-libs/duniter-server/src/legacy/tx_history.rs @@ -16,32 +16,14 @@ use crate::*; impl DuniterServer { - pub fn get_transactions_history(&self, pubkey: PublicKey) -> KvResult<TxsHistory> { - self.dbs_pool - .execute(move |dbs| { - duniter_gva_dbs_reader::txs_history::get_transactions_history_for_bma( - &dbs.gva_db, - &dbs.txs_mp_db, - pubkey, - ) - }) - .expect("dbs pool disconnected") + pub fn get_transactions_history(&self, pubkey: PublicKey) -> KvResult<TxsHistoryForBma> { + get_transactions_history_for_bma(&self.dbs_pool, self.profile_path_opt.as_deref(), pubkey) } pub fn get_tx_by_hash( &self, hash: Hash, ) -> KvResult<Option<(TransactionDocumentV10, Option<BlockNumber>)>> { - self.dbs_pool - .execute(move |dbs| { - if let Some(tx) = dbs.txs_mp_db.txs().get(&HashKeyV2(hash))? { - Ok(Some((tx.0, None))) - } else if let Some(tx_db) = dbs.gva_db.txs().get(&HashKeyV2(hash))? { - Ok(Some((tx_db.tx, Some(tx_db.written_block.number)))) - } else { - Ok(None) - } - }) - .expect("dbs pool disconnected") + get_tx_by_hash(&self.dbs_pool, hash, self.profile_path_opt.as_deref()) } } diff --git a/rust-libs/duniter-server/src/lib.rs b/rust-libs/duniter-server/src/lib.rs index 900ac5f02871025f61a46af69b42dca792921e13..1188466784a9db47d79ec262784189294bd8f11d 100644 --- a/rust-libs/duniter-server/src/lib.rs +++ b/rust-libs/duniter-server/src/lib.rs @@ -24,9 +24,12 @@ mod legacy; -pub use duniter_conf::DuniterConf; -pub use duniter_dbs::{kv_typed::prelude::KvResult, smallvec, DunpHeadDbV1, DunpNodeIdV1Db}; -pub use duniter_gva::{GvaConf, GvaModule, PeerCardStringified}; +pub use duniter_conf::{gva_conf::GvaConf, DuniterConf}; +pub use duniter_dbs::{ + kv_typed::prelude::KvResult, smallvec, DunpHeadDbV1, DunpNodeIdV1Db, PeerCardDbV1, +}; +#[cfg(feature = "gva")] +pub use duniter_gva::GvaModule; use anyhow::Context; use dubp::common::crypto::keys::ed25519::PublicKey; @@ -39,19 +42,29 @@ use duniter_dbs::{ databases::{ bc_v2::BcV2Db, cm_v1::{CmV1DbReadable, CmV1DbWritable}, - gva_v1::GvaV1DbReadable, txs_mp_v2::TxsMpV2DbReadable, }, kv_typed::prelude::*, - HashKeyV2, PendingTxDbV2, PubKeyKeyV2, + PendingTxDbV2, PubKeyKeyV2, }; use duniter_dbs::{prelude::*, BlockMetaV2, FileBackend}; -use duniter_gva_dbs_reader::txs_history::TxsHistory; use duniter_mempools::{Mempools, TxMpError, TxsMempool}; -use duniter_module::{plug_duniter_modules, DuniterModule as _, Endpoint}; +use duniter_module::{plug_duniter_modules, Endpoint, TxsHistoryForBma}; use fast_threadpool::ThreadPoolConfig; use resiter::filter::Filter; -use std::{collections::BTreeMap, path::Path}; +use std::{ + collections::BTreeMap, + path::{Path, PathBuf}, +}; + +cfg_if::cfg_if! { + if #[cfg(feature = "gva")] { + use duniter_module::DuniterModule as _; + plug_duniter_modules!([GvaModule], TxsHistoryForBma); + } else { + plug_duniter_modules!([], TxsHistoryForBma); + } +} #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum DuniterCommand { @@ -63,18 +76,17 @@ pub struct DuniterServer { bc_db: BcV2Db<FileBackend>, conf: DuniterConf, current: Option<BlockMetaV2>, - dbs_pool: fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + dbs_pool: fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, pending_txs_subscriber: flume::Receiver<Arc<Events<duniter_dbs::databases::txs_mp_v2::TxsEvent>>>, + profile_path_opt: Option<PathBuf>, txs_mempool: TxsMempool, } -plug_duniter_modules!([GvaModule]); - #[cfg(not(test))] type DuniterServerInstance = DuniterServer; #[cfg(test)] -type DuniterServerInstance = (DuniterServer, DuniterDbs<FileBackend>); +type DuniterServerInstance = (DuniterServer, SharedDbs<FileBackend>); impl DuniterServer { #[cfg(test)] @@ -91,7 +103,7 @@ impl DuniterServer { command_name: Option<String>, conf: DuniterConf, currency: String, - home_path_opt: Option<&Path>, + profile_path_opt: Option<&Path>, software_version: &'static str, ) -> anyhow::Result<DuniterServerInstance> { let command = match command_name.unwrap_or_default().as_str() { @@ -102,7 +114,7 @@ impl DuniterServer { let txs_mempool = TxsMempool::new(conf.txs_mempool_size); log::info!("open duniter databases..."); - let (bc_db, dbs) = duniter_dbs::open_dbs(home_path_opt); + let (bc_db, dbs) = duniter_dbs::open_dbs(profile_path_opt); log::info!("Databases successfully opened."); let current = duniter_dbs_read_ops::get_current_block_meta(&dbs.bc_db_ro) .context("Fail to get current")?; @@ -118,45 +130,34 @@ impl DuniterServer { .subscribe(s) .context("Fail to subscribe to txs col")?; - let threadpool = if home_path_opt.is_some() { - log::info!("start dbs threadpool..."); - - #[cfg(test)] - let threadpool = - fast_threadpool::ThreadPool::start(ThreadPoolConfig::default(), dbs.clone()); - #[cfg(not(test))] - let threadpool = fast_threadpool::ThreadPool::start(ThreadPoolConfig::default(), dbs); - - if command != DuniterCommand::Sync && conf.gva.is_some() { - let mut runtime = tokio::runtime::Builder::new() - .threaded_scheduler() - .enable_all() - .build()?; - let conf_clone = conf.clone(); - let threadpool_async_handler = threadpool.async_handler(); - std::thread::spawn(move || { - runtime - .block_on(start_duniter_modules( - &conf_clone, - currency, - threadpool_async_handler, - Mempools { txs: txs_mempool }, - None, - software_version, - )) - .context("Fail to start duniter modules") - }); - } - threadpool - } else { - cfg_if::cfg_if! { - if #[cfg(test)] { - fast_threadpool::ThreadPool::start(ThreadPoolConfig::low(), dbs.clone()) - } else { - fast_threadpool::ThreadPool::start(ThreadPoolConfig::low(), dbs) - } - } - }; + log::info!("start dbs threadpool..."); + + #[cfg(test)] + let threadpool = + fast_threadpool::ThreadPool::start(ThreadPoolConfig::default(), dbs.clone()); + #[cfg(not(test))] + let threadpool = fast_threadpool::ThreadPool::start(ThreadPoolConfig::default(), dbs); + + if command != DuniterCommand::Sync && conf.gva.is_some() { + let mut runtime = tokio::runtime::Builder::new() + .threaded_scheduler() + .enable_all() + .build()?; + let conf_clone = conf.clone(); + let threadpool_async_handler = threadpool.async_handler(); + std::thread::spawn(move || { + runtime + .block_on(start_duniter_modules( + &conf_clone, + currency, + threadpool_async_handler, + Mempools { txs: txs_mempool }, + None, + software_version, + )) + .context("Fail to start duniter modules") + }); + } let duniter_server = DuniterServer { bc_db, @@ -164,6 +165,7 @@ impl DuniterServer { current, dbs_pool: threadpool.into_sync_handler(), pending_txs_subscriber, + profile_path_opt: profile_path_opt.map(ToOwned::to_owned), txs_mempool, }; cfg_if::cfg_if! { diff --git a/rust-libs/modules/gva/src/entities.rs b/rust-libs/modules/gva/src/entities.rs index 6aac30cd2524c60472109e77d0009ebec6230512..7eda554e30eda08e123bef2be82430788e182877 100644 --- a/rust-libs/modules/gva/src/entities.rs +++ b/rust-libs/modules/gva/src/entities.rs @@ -29,6 +29,31 @@ pub(crate) struct AmountWithBase { pub(crate) base: i32, } +#[derive(Default, async_graphql::SimpleObject)] +#[graphql(name = "Peer")] +pub struct PeerCardGva { + pub version: u32, + pub currency: String, + pub pubkey: String, + pub blockstamp: String, + pub endpoints: Vec<String>, + pub status: String, + pub signature: String, +} +impl From<duniter_dbs::PeerCardDbV1> for PeerCardGva { + fn from(peer: duniter_dbs::PeerCardDbV1) -> Self { + Self { + version: peer.version, + currency: peer.currency, + pubkey: peer.pubkey, + blockstamp: peer.blockstamp, + endpoints: peer.endpoints, + status: peer.status, + signature: peer.signature, + } + } +} + pub(crate) enum RawTxOrChanges { FinalTx(String), Changes(Vec<String>), diff --git a/rust-libs/modules/gva/src/lib.rs b/rust-libs/modules/gva/src/lib.rs index 5328f9338431fc1995eb1f650e6b11d77d4093fe..ce60e01d342dcb28a06987ac4117421f56961b81 100644 --- a/rust-libs/modules/gva/src/lib.rs +++ b/rust-libs/modules/gva/src/lib.rs @@ -38,7 +38,7 @@ mod warp_; use crate::entities::{ tx_gva::TxGva, ud_gva::{CurrentUdGva, RevalUdGva, UdGva}, - AggregateSum, AmountWithBase, RawTxOrChanges, Sum, TxsHistoryGva, UtxoGva, + AggregateSum, AmountWithBase, PeerCardGva, RawTxOrChanges, Sum, TxsHistoryGva, UtxoGva, }; use crate::inputs::{TxIssuer, TxRecipient, UdsFilter}; use crate::inputs_validators::TxCommentValidator; @@ -50,14 +50,17 @@ use crate::tests::create_dbs_reader; use crate::tests::DbsReader; use async_graphql::http::GraphQLPlaygroundConfig; use async_graphql::validators::{IntGreaterThan, ListMinLength, StringMaxLength, StringMinLength}; -use dubp::block::DubpBlockV10; use dubp::common::crypto::keys::{ed25519::PublicKey, KeyPair as _, PublicKey as _}; use dubp::common::prelude::*; use dubp::documents::prelude::*; use dubp::documents::transaction::{TransactionDocumentTrait, TransactionDocumentV10}; use dubp::documents_parser::prelude::*; use dubp::wallet::prelude::*; -use duniter_dbs::databases::{gva_v1::GvaV1DbRo, txs_mp_v2::TxsMpV2DbReadable}; +use dubp::{block::DubpBlockV10, crypto::hashs::Hash}; +use duniter_dbs::databases::{ + gva_v1::{GvaV1Db, GvaV1DbReadable, GvaV1DbRo, GvaV1DbWritable}, + txs_mp_v2::TxsMpV2DbReadable, +}; use duniter_dbs::prelude::*; use duniter_dbs::{kv_typed::prelude::*, FileBackend, TxDbV2}; #[cfg(not(test))] @@ -77,18 +80,15 @@ use warp::{http::Response as HttpResponse, Filter as _, Rejection, Stream}; static GVA_DB_RO: once_cell::sync::OnceCell<GvaV1DbRo<FileBackend>> = once_cell::sync::OnceCell::new(); -/*static GVA_DB_RW: once_cell::sync::OnceCell<GvaV1Db<FileBackend>> = +static GVA_DB_RW: once_cell::sync::OnceCell<GvaV1Db<FileBackend>> = once_cell::sync::OnceCell::new(); -fn get_gva_db() -> &GvaV1Db<FileBackend> { - todo!() //ESZ -}*/ - #[derive(Debug)] pub struct GvaModule { conf: Option<GvaConf>, currency: String, - dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, + dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, + gva_db_ro: &'static GvaV1DbRo<FileBackend>, mempools: Mempools, self_pubkey: PublicKey, software_version: &'static str, @@ -99,12 +99,13 @@ impl duniter_module::DuniterModule for GvaModule { fn apply_block( block: Arc<DubpBlockV10>, conf: &duniter_conf::DuniterConf, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, - _profile_path_opt: Option<&Path>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, + profile_path_opt: Option<&Path>, ) -> Result<Option<JoinHandle<KvResult<()>>>, ThreadPoolDisconnected> { + let gva_db = GvaModule::get_gva_db_rw(profile_path_opt); if conf.gva.is_some() { - Ok(Some(dbs_pool.launch(move |dbs| { - duniter_gva_db_writer::apply_block(&block, &dbs.gva_db) + Ok(Some(dbs_pool.launch(move |_| { + duniter_gva_db_writer::apply_block(&block, gva_db) })?)) } else { Ok(None) @@ -113,13 +114,14 @@ impl duniter_module::DuniterModule for GvaModule { fn apply_chunk_of_blocks( blocks: Arc<[DubpBlockV10]>, conf: &duniter_conf::DuniterConf, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, - _profile_path_opt: Option<&Path>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, + profile_path_opt: Option<&Path>, ) -> Result<Option<JoinHandle<KvResult<()>>>, ThreadPoolDisconnected> { + let gva_db = GvaModule::get_gva_db_rw(profile_path_opt); if conf.gva.is_some() { - Ok(Some(dbs_pool.launch(move |dbs| { + Ok(Some(dbs_pool.launch(move |_| { for block in blocks.deref() { - duniter_gva_db_writer::apply_block(&block, &dbs.gva_db)?; + duniter_gva_db_writer::apply_block(&block, gva_db)?; } Ok::<_, KvError>(()) })?)) @@ -130,12 +132,13 @@ impl duniter_module::DuniterModule for GvaModule { fn revert_block( block: Arc<DubpBlockV10>, conf: &duniter_conf::DuniterConf, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, - _profile_path_opt: Option<&Path>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, + profile_path_opt: Option<&Path>, ) -> Result<Option<JoinHandle<KvResult<()>>>, ThreadPoolDisconnected> { + let gva_db = GvaModule::get_gva_db_rw(profile_path_opt); if conf.gva.is_some() { - Ok(Some(dbs_pool.launch(move |dbs| { - duniter_gva_db_writer::revert_block(&block, &dbs.gva_db) + Ok(Some(dbs_pool.launch(move |_| { + duniter_gva_db_writer::revert_block(&block, gva_db) })?)) } else { Ok(None) @@ -144,9 +147,9 @@ impl duniter_module::DuniterModule for GvaModule { fn init( conf: &duniter_conf::DuniterConf, currency: &str, - dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, + dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, mempools: Mempools, - _profile_path_opt: Option<&std::path::Path>, + profile_path_opt: Option<&Path>, software_version: &'static str, ) -> anyhow::Result<(Self, Vec<duniter_module::Endpoint>)> { let mut endpoints = Vec::new(); @@ -180,6 +183,7 @@ impl duniter_module::DuniterModule for GvaModule { conf: conf.gva.to_owned(), currency: currency.to_owned(), dbs_pool: dbs_pool.to_owned(), + gva_db_ro: GvaModule::get_gva_db_ro(profile_path_opt), mempools, self_pubkey: conf.self_key_pair.public_key(), software_version, @@ -189,44 +193,118 @@ impl duniter_module::DuniterModule for GvaModule { } async fn start(self) -> anyhow::Result<()> { - let GvaModule { - conf, - currency, - dbs_pool, - mempools, - self_pubkey, - software_version, - } = self; - - if let Some(conf) = conf { - GvaModule::start_inner( + // Do not start GVA server on js tests + if std::env::var_os("DUNITER_JS_TESTS") != Some("yes".into()) { + let GvaModule { conf, currency, dbs_pool, + gva_db_ro, mempools, self_pubkey, software_version, - ) - .await + } = self; + + if let Some(conf) = conf { + GvaModule::start_inner( + conf, + currency, + dbs_pool, + gva_db_ro, + mempools, + self_pubkey, + software_version, + ) + .await + } } Ok(()) } + // Needed for BMA only, will be removed when the migration is complete. + fn get_transactions_history_for_bma( + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, + profile_path_opt: Option<&Path>, + pubkey: PublicKey, + ) -> KvResult<Option<duniter_module::TxsHistoryForBma>> { + let gva_db = GvaModule::get_gva_db_ro(profile_path_opt); + let duniter_gva_dbs_reader::txs_history::TxsHistory { + sent, + received, + sending, + pending, + } = dbs_pool + .execute(move |dbs| { + duniter_gva_dbs_reader::txs_history::get_transactions_history_for_bma( + gva_db, + &dbs.txs_mp_db, + pubkey, + ) + }) + .expect("dbs pool disconnected")?; + Ok(Some(duniter_module::TxsHistoryForBma { + sent: sent + .into_iter() + .map( + |TxDbV2 { + tx, + written_block, + written_time, + }| (tx, written_block, written_time), + ) + .collect(), + received: received + .into_iter() + .map( + |TxDbV2 { + tx, + written_block, + written_time, + }| (tx, written_block, written_time), + ) + .collect(), + sending, + pending, + })) + } + // Needed for BMA only, will be removed when the migration is complete. + fn get_tx_by_hash( + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, + hash: Hash, + profile_path_opt: Option<&Path>, + ) -> KvResult<Option<(TransactionDocumentV10, Option<BlockNumber>)>> { + let gva_db = GvaModule::get_gva_db_ro(profile_path_opt); + dbs_pool + .execute(move |dbs| { + if let Some(tx) = dbs.txs_mp_db.txs().get(&duniter_dbs::HashKeyV2(hash))? { + Ok(Some((tx.0, None))) + } else if let Some(tx_db) = gva_db.txs().get(&duniter_dbs::HashKeyV2(hash))? { + Ok(Some((tx_db.tx, Some(tx_db.written_block.number)))) + } else { + Ok(None) + } + }) + .expect("dbs pool disconnected") + } } impl GvaModule { - async fn get_gva_db_ro( - dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, - ) -> &'static GvaV1DbRo<FileBackend> { + fn get_gva_db_ro(profile_path_opt: Option<&Path>) -> &'static GvaV1DbRo<FileBackend> { use duniter_dbs::databases::gva_v1::GvaV1DbWritable as _; - dbs_pool - .execute(|dbs| GVA_DB_RO.get_or_init(|| dbs.gva_db.get_ro_handler())) - .await - .expect("dbs pool disconnected") + GVA_DB_RO.get_or_init(|| GvaModule::get_gva_db_rw(profile_path_opt).get_ro_handler()) + } + pub fn get_gva_db_rw(profile_path_opt: Option<&Path>) -> &'static GvaV1Db<FileBackend> { + GVA_DB_RW.get_or_init(|| { + duniter_dbs::databases::gva_v1::GvaV1Db::<FileBackend>::open( + FileBackend::gen_backend_conf("gva_v1", profile_path_opt), + ) + .expect("Fail to open GVA DB") + }) } async fn start_inner( conf: GvaConf, currency: String, - dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, + dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, + gva_db_ro: &'static GvaV1DbRo<FileBackend>, mempools: Mempools, self_pubkey: PublicKey, software_version: &'static str, @@ -238,7 +316,7 @@ impl GvaModule { subscriptions::SubscriptionRoot::default(), ) .data(schema::SchemaData { - dbs_reader: create_dbs_reader(Self::get_gva_db_ro(&dbs_pool).await), + dbs_reader: create_dbs_reader(gva_db_ro), dbs_pool, server_meta_data: ServerMetaData { currency, @@ -323,41 +401,6 @@ pub struct ServerMetaData { pub software_version: &'static str, } -#[derive( - async_graphql::SimpleObject, - Clone, - Debug, - Default, - Eq, - PartialEq, - serde::Deserialize, - serde::Serialize, -)] -#[serde(rename_all = "camelCase")] -#[graphql(name = "PeerCard")] -pub struct PeerCardStringified { - pub version: u32, - pub currency: String, - pub pubkey: String, - pub blockstamp: String, - pub endpoints: Vec<String>, - pub status: String, - pub signature: String, -} -impl From<duniter_dbs::PeerCardDbV1> for PeerCardStringified { - fn from(peer: duniter_dbs::PeerCardDbV1) -> Self { - Self { - version: peer.version, - currency: peer.currency, - pubkey: peer.pubkey, - blockstamp: peer.blockstamp, - endpoints: peer.endpoints, - status: peer.status, - signature: peer.signature, - } - } -} - #[cfg(test)] mod tests { use super::*; @@ -429,7 +472,7 @@ mod tests { } pub(crate) fn create_schema(dbs_ops: MockDbsReader) -> KvResult<GraphQlSchema> { - let dbs = DuniterDbs::mem()?; + let dbs = SharedDbs::mem()?; let threadpool = fast_threadpool::ThreadPool::start(ThreadPoolConfig::default(), dbs); Ok(async_graphql::Schema::build( queries::QueryRoot::default(), @@ -460,7 +503,7 @@ mod tests { #[tokio::test] #[ignore] async fn launch_mem_gva() -> anyhow::Result<()> { - let dbs = unwrap!(DuniterDbs::mem()); + let dbs = unwrap!(SharedDbs::mem()); let threadpool = fast_threadpool::ThreadPool::start(ThreadPoolConfig::default(), dbs); GvaModule::init( diff --git a/rust-libs/modules/gva/src/queries.rs b/rust-libs/modules/gva/src/queries.rs index f9ffeb9e075e119a45713815543f82d0ebc52bb5..ce5ceff9e557d55a1448f255a4b5de15b2ac1bd2 100644 --- a/rust-libs/modules/gva/src/queries.rs +++ b/rust-libs/modules/gva/src/queries.rs @@ -46,7 +46,7 @@ impl Node { async fn peer( &self, ctx: &async_graphql::Context<'_>, - ) -> async_graphql::Result<Option<PeerCardStringified>> { + ) -> async_graphql::Result<Option<PeerCardGva>> { let data = ctx.data::<SchemaData>()?; Ok(data diff --git a/rust-libs/modules/gva/src/queries/utxos_of_script.rs b/rust-libs/modules/gva/src/queries/utxos_of_script.rs index cccaa81244eecaedf7a22b7f8651eb12b62d1724..d50a2f22c25754a191083ce146ad8f22434e30a0 100644 --- a/rust-libs/modules/gva/src/queries/utxos_of_script.rs +++ b/rust-libs/modules/gva/src/queries/utxos_of_script.rs @@ -15,7 +15,6 @@ use crate::*; use async_graphql::connection::*; -use duniter_dbs::databases::gva_v1::GvaV1DbReadable; use duniter_gva_dbs_reader::{ utxos::{UtxoCursor, UtxosWithSum}, PagedData, @@ -63,12 +62,7 @@ impl UtxosQuery { )?; let mut times = Vec::with_capacity(paged_data.data.utxos.len()); for (UtxoCursor { block_number, .. }, _sa) in &paged_data.data.utxos { - times.push( - dbs.gva_db - .blockchain_time() - .get(&U32BE(block_number.0))? - .unwrap_or_else(|| unreachable!()), - ); + times.push(db_reader.get_blockchain_time(*block_number)?); } Ok::<_, anyhow::Error>((paged_data, times)) } else { diff --git a/rust-libs/modules/gva/src/schema.rs b/rust-libs/modules/gva/src/schema.rs index c4540e7bb64d7cc500d2aae09697c20ad5f7be87..3ea5213d24ff72788b5f1fcbeecd5f2539ecbdf9 100644 --- a/rust-libs/modules/gva/src/schema.rs +++ b/rust-libs/modules/gva/src/schema.rs @@ -21,7 +21,7 @@ pub(crate) type GraphQlSchema = async_graphql::Schema< crate::subscriptions::SubscriptionRoot, >; pub(crate) struct SchemaData { - pub(crate) dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, + pub(crate) dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, pub(crate) dbs_reader: DbsReader, pub(crate) server_meta_data: ServerMetaData, pub(crate) txs_mempool: TxsMempool, diff --git a/rust-libs/tests/duniter-integration-tests/Cargo.toml b/rust-libs/tests/duniter-integration-tests/Cargo.toml index 32b78068ce82c8a002aedc5fe0c53902d8027ea8..cf913bcb60047ed426a0e6d5e74222a51f6021d8 100644 --- a/rust-libs/tests/duniter-integration-tests/Cargo.toml +++ b/rust-libs/tests/duniter-integration-tests/Cargo.toml @@ -12,10 +12,9 @@ duniter-conf = { path = "../../duniter-conf" } duniter-dbs = { path = "../../duniter-dbs" } duniter-dbs-read-ops = { path = "../../duniter-dbs-read-ops" } duniter-dbs-write-ops = { path = "../../duniter-dbs-write-ops" } -duniter-gva = { path = "../../modules/gva" } duniter-mempools = { path = "../../duniter-mempools" } duniter-module = { path = "../../duniter-module" } -duniter-server = { path = "../../duniter-server" } +duniter-server = { path = "../../duniter-server", features = ["gva"] } fast-threadpool = "0.2.2" flume = "0.9.1" log = "0.4.11" diff --git a/rust-libs/tests/duniter-integration-tests/src/lib.rs b/rust-libs/tests/duniter-integration-tests/src/lib.rs index 4260a8b612d0e6fcf02500bd997dfec13a2aa6c9..ac460624c47fa944e4f92173a294238131652396 100644 --- a/rust-libs/tests/duniter-integration-tests/src/lib.rs +++ b/rust-libs/tests/duniter-integration-tests/src/lib.rs @@ -59,6 +59,7 @@ mod tests { hash: None, } .build_with_signature(smallvec![]); + server.add_pending_tx_force(tx.clone())?; let txs_history = server.get_transactions_history(PublicKey::default())?;