diff --git a/Cargo.lock b/Cargo.lock index 6271a9a55d5823fa3259a202621f618e325eda53..78d354aaf1a73f5b27113cf23af82c7e1ca5859f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1253,6 +1253,7 @@ name = "duniter-server" version = "1.8.1" dependencies = [ "anyhow", + "cfg-if 1.0.0", "dubp", "duniter-conf", "duniter-dbs", diff --git a/rust-libs/duniter-module/src/lib.rs b/rust-libs/duniter-module/src/lib.rs index 1ad5b71c1e47db99b081a716b23488e73b0ed206..bc804f974535c55b21c40a3531fcdf147cd63a56 100644 --- a/rust-libs/duniter-module/src/lib.rs +++ b/rust-libs/duniter-module/src/lib.rs @@ -29,6 +29,8 @@ use duniter_mempools::Mempools; use fast_threadpool::{JoinHandle, ThreadPoolDisconnected}; use std::path::Path; +pub const SOFTWARE_NAME: &str = "duniter"; + pub type Endpoint = String; #[async_trait::async_trait] diff --git a/rust-libs/duniter-server/Cargo.toml b/rust-libs/duniter-server/Cargo.toml index de8b7bb4d7f9ad88ab303ab0dfad590244a8bcb4..f3e120d72cd16e335e12c0649323463c9e85a255 100644 --- a/rust-libs/duniter-server/Cargo.toml +++ b/rust-libs/duniter-server/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] anyhow = "1.0.34" +cfg-if = "1.0.0" dubp = { version = "0.32.3" } duniter-conf = { path = "../duniter-conf" } duniter-dbs = { path = "../duniter-dbs" } @@ -22,3 +23,6 @@ log = "0.4.11" paste = "1.0.2" resiter = "0.4.0" tokio = { version = "0.2.22", features = ["io-util", "rt-threaded"] } + +[dev-dependencies] +duniter-dbs = { path = "../duniter-dbs", features = ["mem"] } diff --git a/rust-libs/duniter-server/src/legacy.rs b/rust-libs/duniter-server/src/legacy.rs new file mode 100644 index 0000000000000000000000000000000000000000..d1d0a65b57e5f38f640ac074d2f9827e1f9ea5be --- /dev/null +++ b/rust-libs/duniter-server/src/legacy.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/>. + +//! Legacy functions intended to be used by DuniterJs uniquely. This module will be removed when the migration is complete. + +mod block_indexer; +mod dunp; +mod tx_history; +mod txs_mempool; diff --git a/rust-libs/duniter-server/src/legacy/block_indexer.rs b/rust-libs/duniter-server/src/legacy/block_indexer.rs new file mode 100644 index 0000000000000000000000000000000000000000..4b3483e1c22e9d6b89c11884adc683eccc923c3d --- /dev/null +++ b/rust-libs/duniter-server/src/legacy/block_indexer.rs @@ -0,0 +1,69 @@ +// 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::*; + +impl DuniterServer { + 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 revert_block(&mut self, block: DubpBlockV10Stringified) -> KvResult<()> { + let block = Arc::new( + DubpBlockV10::from_string_object(&block) + .map_err(|e| KvError::DeserError(format!("{}", e)))?, + ); + let block_arc_clone = Arc::clone(&block); + let txs_mp_job_handle = self + .dbs_pool + .launch(move |dbs| { + duniter_dbs_write_ops::txs_mp::revert_block( + block_arc_clone.transactions(), + &dbs.txs_mp_db, + ) + }) + .expect("dbs pool disconnected"); + self.current = duniter_dbs_write_ops::bc::revert_block(&self.bc_db, &block)?; + txs_mp_job_handle.join().expect("dbs pool disconnected")?; + revert_block_modules(block, &self.conf, &self.dbs_pool, None) + } +} diff --git a/rust-libs/duniter-server/src/legacy/dunp.rs b/rust-libs/duniter-server/src/legacy/dunp.rs new file mode 100644 index 0000000000000000000000000000000000000000..020e32e708c84dab381d57739c0bee5f08a88ec8 --- /dev/null +++ b/rust-libs/duniter-server/src/legacy/dunp.rs @@ -0,0 +1,166 @@ +// 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::*; + +impl DuniterServer { + 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_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 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 update_self_peer(&self, new_peer_card: PeerCardStringified) { + 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, + }, + ) + .expect("fail to write on memory db") + }) + .expect("dbs pool disconnected") + } +} + +#[cfg(test)] +mod tests { + use dubp::crypto::keys::{ + ed25519::{PublicKey, Signature}, + PublicKey as _, + }; + use duniter_dbs::PeerCardDbV1; + + use super::*; + + #[test] + fn test_receive_new_heads() -> anyhow::Result<()> { + use duniter_dbs::databases::cm_v1::CmV1DbReadable as _; + let (server, dbs) = DuniterServer::test(DuniterConf::default())?; + + let head = ( + duniter_dbs::DunpNodeIdV1Db::new(53, PublicKey::default()), + duniter_dbs::DunpHeadDbV1 { + api: "WS2P".to_owned(), + pubkey: PublicKey::default(), + blockstamp: Blockstamp::default(), + software: duniter_module::SOFTWARE_NAME.to_owned(), + software_version: "test".to_owned(), + pow_prefix: 1, + free_member_room: 0, + free_mirror_room: 0, + signature: Signature::default(), + }, + ); + + assert_eq!(dbs.cm_db.dunp_heads_old().count()?, 0); + server.receive_new_heads(vec![head.clone()])?; + assert_eq!(dbs.cm_db.dunp_heads_old().count()?, 1); + assert_eq!(dbs.cm_db.dunp_heads_old().get(&head.0)?, Some(head.1)); + + Ok(()) + } + + #[test] + fn test_save_peer() -> anyhow::Result<()> { + use duniter_dbs::databases::dunp_v1::DunpV1DbReadable as _; + let (server, dbs) = DuniterServer::test(DuniterConf::default())?; + + let peer = PeerCardStringified { + version: 0, + currency: "test".to_owned(), + pubkey: "82NdD9eEbXSjRJXeJdqf56xkpu6taTfTeEqtAtmtbyXY".to_owned(), + blockstamp: "379922-0000001D97770A8203062F9E618F29FFAA2EF4218649FCE6DD13E01C3932E943".to_owned(), + endpoints: vec![], + status: "UP".to_owned(), + signature: "KBaoJuKIfkWJO015BTegUN8l81VYPfleVUfQUwPRPAAF1oB398hDb1bX/QUFe+3CKFz57aGT8bB745mz90x5Ag==".to_owned(), + }; + let pubkey = PublicKey::from_base58(&peer.pubkey)?; + + assert_eq!(dbs.dunp_db.peers_old().count()?, 0); + server.save_peer(peer.clone())?; + + 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, + }) + ); + + Ok(()) + } +} diff --git a/rust-libs/duniter-server/src/legacy/tx_history.rs b/rust-libs/duniter-server/src/legacy/tx_history.rs new file mode 100644 index 0000000000000000000000000000000000000000..4c55b2fc03f01f495b4af5edffe09b5fc0fcc631 --- /dev/null +++ b/rust-libs/duniter-server/src/legacy/tx_history.rs @@ -0,0 +1,47 @@ +// 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::*; + +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_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") + } +} diff --git a/rust-libs/duniter-server/src/legacy/txs_mempool.rs b/rust-libs/duniter-server/src/legacy/txs_mempool.rs new file mode 100644 index 0000000000000000000000000000000000000000..528a45b603e305424acb290b0eb6517d0c10ae65 --- /dev/null +++ b/rust-libs/duniter-server/src/legacy/txs_mempool.rs @@ -0,0 +1,117 @@ +// 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::*; + +impl DuniterServer { + pub fn accept_new_tx( + &self, + tx: TransactionDocumentV10, + server_pubkey: PublicKey, + ) -> KvResult<bool> { + let txs_mempool = self.txs_mempool; + match self + .dbs_pool + .execute(move |dbs| { + txs_mempool.accept_new_tx(&dbs.bc_db_ro, server_pubkey, tx, &dbs.txs_mp_db) + }) + .expect("dbs pool discorrected") + { + Ok(()) => Ok(true), + Err(TxMpError::Db(e)) => Err(e), + Err(_) => Ok(false), + } + } + pub fn add_pending_tx_force(&self, tx: TransactionDocumentV10) -> KvResult<()> { + let txs_mempool = self.txs_mempool; + self.dbs_pool + .execute(move |dbs| txs_mempool.add_pending_tx_force(&dbs.txs_mp_db, &tx)) + .expect("dbs pool disconnected") + } + pub fn get_self_endpoints(&self) -> anyhow::Result<Vec<Endpoint>> { + if let Some(self_peer) = self + .dbs_pool + .execute(|dbs| dbs.cm_db.self_peer_old().get(&()))? + .context("fail to get self endpoints")? + { + Ok(self_peer.endpoints) + } else { + Ok(vec![]) + } + } + pub fn get_mempool_txs_free_rooms(&self) -> KvResult<usize> { + let txs_mempool = self.txs_mempool; + self.dbs_pool + .execute(move |dbs| txs_mempool.get_free_rooms(&dbs.txs_mp_db)) + .expect("dbs pool discorrected") + } + pub fn get_new_pending_txs(&self) -> KvResult<Vec<TransactionDocumentV10>> { + let mut new_pending_txs = BTreeMap::new(); + for events in self.pending_txs_subscriber.drain() { + use std::ops::Deref as _; + for event in events.deref() { + match event { + duniter_dbs::databases::txs_mp_v2::TxsEvent::Upsert { key, value } => { + new_pending_txs.insert(key.0, value.0.clone()); + } + duniter_dbs::databases::txs_mp_v2::TxsEvent::Remove { key } => { + new_pending_txs.remove(&key.0); + } + _ => (), + } + } + } + Ok(new_pending_txs.into_iter().map(|(_k, v)| v).collect()) + } + pub fn get_pending_txs( + &self, + _blockchain_time: i64, + min_version: usize, + ) -> KvResult<Vec<PendingTxDbV2>> { + self.dbs_pool + .execute(move |dbs| { + dbs.txs_mp_db.txs().iter(.., |it| { + it.values() + .filter_ok(|tx| tx.0.version() >= min_version) + .collect() + }) + }) + .expect("dbs pool disconnected") + } + pub fn remove_all_pending_txs(&self) -> KvResult<()> { + self.dbs_pool + .execute(move |dbs| { + duniter_dbs_write_ops::txs_mp::remove_all_pending_txs(&dbs.txs_mp_db) + }) + .expect("dbs pool disconnected") + } + pub fn remove_pending_tx_by_hash(&self, hash: Hash) -> KvResult<()> { + self.dbs_pool + .execute(move |dbs| { + duniter_dbs_write_ops::txs_mp::remove_pending_tx_by_hash(&dbs.txs_mp_db, hash) + }) + .expect("dbs pool disconnected") + } + pub fn trim_expired_non_written_txs(&self, limit_time: i64) -> KvResult<()> { + self.dbs_pool + .execute(move |dbs| { + duniter_dbs_write_ops::txs_mp::trim_expired_non_written_txs( + &dbs.txs_mp_db, + limit_time, + ) + }) + .expect("dbs pool disconnected") + } +} diff --git a/rust-libs/duniter-server/src/lib.rs b/rust-libs/duniter-server/src/lib.rs index ac936bfedd8bdc46c702e835e9323baa2ff96362..900ac5f02871025f61a46af69b42dca792921e13 100644 --- a/rust-libs/duniter-server/src/lib.rs +++ b/rust-libs/duniter-server/src/lib.rs @@ -22,6 +22,8 @@ unused_import_braces )] +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}; @@ -69,14 +71,29 @@ pub struct DuniterServer { plug_duniter_modules!([GvaModule]); +#[cfg(not(test))] +type DuniterServerInstance = DuniterServer; +#[cfg(test)] +type DuniterServerInstance = (DuniterServer, DuniterDbs<FileBackend>); + impl DuniterServer { + #[cfg(test)] + pub(crate) fn test(conf: DuniterConf) -> anyhow::Result<DuniterServerInstance> { + DuniterServer::start( + None, + conf, + "test".to_owned(), + None, + duniter_module::SOFTWARE_NAME, + ) + } pub fn start( command_name: Option<String>, conf: DuniterConf, currency: String, home_path_opt: Option<&Path>, software_version: &'static str, - ) -> anyhow::Result<Self> { + ) -> anyhow::Result<DuniterServerInstance> { let command = match command_name.unwrap_or_default().as_str() { "sync" => DuniterCommand::Sync, _ => DuniterCommand::Start, @@ -103,6 +120,11 @@ impl DuniterServer { 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() { @@ -127,271 +149,29 @@ impl DuniterServer { } threadpool } else { - fast_threadpool::ThreadPool::start(ThreadPoolConfig::low(), dbs) + cfg_if::cfg_if! { + if #[cfg(test)] { + fast_threadpool::ThreadPool::start(ThreadPoolConfig::low(), dbs.clone()) + } else { + fast_threadpool::ThreadPool::start(ThreadPoolConfig::low(), dbs) + } + } }; - Ok(DuniterServer { + let duniter_server = DuniterServer { bc_db, conf, current, dbs_pool: threadpool.into_sync_handler(), pending_txs_subscriber, txs_mempool, - }) - } - - /* - * READ FUNCTIONS FOR DUNITER JS ONLY - */ - pub fn get_self_endpoints(&self) -> anyhow::Result<Vec<Endpoint>> { - if let Some(self_peer) = self - .dbs_pool - .execute(|dbs| dbs.cm_db.self_peer_old().get(&()))? - .context("fail to get self endpoints")? - { - Ok(self_peer.endpoints) - } else { - Ok(vec![]) - } - } - pub fn accept_new_tx( - &self, - tx: TransactionDocumentV10, - server_pubkey: PublicKey, - ) -> KvResult<bool> { - let txs_mempool = self.txs_mempool; - match self - .dbs_pool - .execute(move |dbs| { - txs_mempool.accept_new_tx(&dbs.bc_db_ro, server_pubkey, tx, &dbs.txs_mp_db) - }) - .expect("dbs pool discorrected") - { - Ok(()) => Ok(true), - Err(TxMpError::Db(e)) => Err(e), - Err(_) => Ok(false), - } - } - pub fn get_mempool_txs_free_rooms(&self) -> KvResult<usize> { - let txs_mempool = self.txs_mempool; - self.dbs_pool - .execute(move |dbs| txs_mempool.get_free_rooms(&dbs.txs_mp_db)) - .expect("dbs pool discorrected") - } - pub fn get_new_pending_txs(&self) -> KvResult<Vec<TransactionDocumentV10>> { - let mut new_pending_txs = BTreeMap::new(); - for events in self.pending_txs_subscriber.drain() { - use std::ops::Deref as _; - for event in events.deref() { - match event { - duniter_dbs::databases::txs_mp_v2::TxsEvent::Upsert { key, value } => { - new_pending_txs.insert(key.0, value.0.clone()); - } - duniter_dbs::databases::txs_mp_v2::TxsEvent::Remove { key } => { - new_pending_txs.remove(&key.0); - } - _ => (), - } + }; + cfg_if::cfg_if! { + if #[cfg(test)] { + Ok((duniter_server, dbs)) + } else { + Ok(duniter_server) } } - Ok(new_pending_txs.into_iter().map(|(_k, v)| v).collect()) - } - pub fn get_pending_txs( - &self, - _blockchain_time: i64, - min_version: usize, - ) -> KvResult<Vec<PendingTxDbV2>> { - self.dbs_pool - .execute(move |dbs| { - dbs.txs_mp_db.txs().iter(.., |it| { - it.values() - .filter_ok(|tx| tx.0.version() >= min_version) - .collect() - }) - }) - .expect("dbs pool disconnected") - } - - 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_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") - } - - /* - * WRITE FUNCTION FOR DUNITER JS ONLY - */ - pub fn add_pending_tx_force(&self, tx: TransactionDocumentV10) -> KvResult<()> { - let txs_mempool = self.txs_mempool; - self.dbs_pool - .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| { - duniter_dbs_write_ops::txs_mp::remove_all_pending_txs(&dbs.txs_mp_db) - }) - .expect("dbs pool disconnected") - } - pub fn remove_pending_tx_by_hash(&self, hash: Hash) -> KvResult<()> { - self.dbs_pool - .execute(move |dbs| { - duniter_dbs_write_ops::txs_mp::remove_pending_tx_by_hash(&dbs.txs_mp_db, hash) - }) - .expect("dbs pool disconnected") - } - pub fn revert_block(&mut self, block: DubpBlockV10Stringified) -> KvResult<()> { - let block = Arc::new( - DubpBlockV10::from_string_object(&block) - .map_err(|e| KvError::DeserError(format!("{}", e)))?, - ); - let block_arc_clone = Arc::clone(&block); - let txs_mp_job_handle = self - .dbs_pool - .launch(move |dbs| { - duniter_dbs_write_ops::txs_mp::revert_block( - block_arc_clone.transactions(), - &dbs.txs_mp_db, - ) - }) - .expect("dbs pool disconnected"); - self.current = duniter_dbs_write_ops::bc::revert_block(&self.bc_db, &block)?; - txs_mp_job_handle.join().expect("dbs pool disconnected")?; - revert_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 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 - .execute(move |dbs| { - duniter_dbs_write_ops::txs_mp::trim_expired_non_written_txs( - &dbs.txs_mp_db, - limit_time, - ) - }) - .expect("dbs pool disconnected") - } - pub fn update_self_peer(&self, new_peer_card: PeerCardStringified) { - 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, - }, - ) - .expect("fail to write on memory db") - }) - .expect("dbs pool disconnected") } } diff --git a/rust-libs/modules/gva/src/lib.rs b/rust-libs/modules/gva/src/lib.rs index 0b1cb6612d5709f1e44fb1f3b1f44e442b21a07d..5328f9338431fc1995eb1f650e6b11d77d4093fe 100644 --- a/rust-libs/modules/gva/src/lib.rs +++ b/rust-libs/modules/gva/src/lib.rs @@ -324,7 +324,14 @@ pub struct ServerMetaData { } #[derive( - async_graphql::SimpleObject, Clone, Debug, Default, serde::Deserialize, serde::Serialize, + async_graphql::SimpleObject, + Clone, + Debug, + Default, + Eq, + PartialEq, + serde::Deserialize, + serde::Serialize, )] #[serde(rename_all = "camelCase")] #[graphql(name = "PeerCard")] diff --git a/rust-libs/modules/gva/src/queries.rs b/rust-libs/modules/gva/src/queries.rs index 2d240cdf35eb1cc29d1b658c36ddaa10c34744c6..f9ffeb9e075e119a45713815543f82d0ebc52bb5 100644 --- a/rust-libs/modules/gva/src/queries.rs +++ b/rust-libs/modules/gva/src/queries.rs @@ -57,7 +57,7 @@ impl Node { } /// Software async fn software(&self) -> &'static str { - "duniter" + duniter_module::SOFTWARE_NAME } /// Software version async fn version(