diff --git a/Cargo.lock b/Cargo.lock index de8ab415dbea90b048fb3c0909992111d53b4af2..a0e5cdbacd0cec6e6f16399a8853a564554afbe7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1070,6 +1070,7 @@ dependencies = [ "dubp", "duniter-dbs", "duniter-dbs-write-ops", + "duniter-gva-db-writer", "fast-threadpool", "rayon", "serde", @@ -1141,6 +1142,7 @@ dependencies = [ "duniter-conf", "duniter-dbs", "duniter-dbs-read-ops", + "duniter-gva-db-writer", "duniter-gva-dbs-reader", "duniter-mempools", "duniter-module", @@ -1159,6 +1161,17 @@ dependencies = [ "warp", ] +[[package]] +name = "duniter-gva-db-writer" +version = "0.1.0" +dependencies = [ + "anyhow", + "dubp", + "duniter-dbs", + "resiter", + "smallvec", +] + [[package]] name = "duniter-gva-dbs-reader" version = "0.1.0" @@ -1346,9 +1359,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fast-threadpool" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9f76ead92b1c1e372f552dcd2e331fb321d6b16886df58ed7586208e211e14" +checksum = "f7b7af2f4b094190e85f8ba81ac02159ca91edc5aacd490eebfcc3f53b444e11" dependencies = [ "async-oneshot", "flume", diff --git a/Cargo.toml b/Cargo.toml index 636eb3e9ac35c9a4062f987c533c82d7e3b28a3a..01a1412185546d1a02bc718e877c3ca0f0fe9399 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ members = [ "rust-libs/duniter-server", "rust-libs/modules/gva", "rust-libs/modules/gva/dbs-reader", + "rust-libs/modules/gva/db-writer", "rust-libs/tests/duniter-integration-tests", "rust-libs/tools/kv_typed" ] diff --git a/rust-bins/duniter-dbex/Cargo.toml b/rust-bins/duniter-dbex/Cargo.toml index 16a8816cf7f98c8483a6bd4d04e662f0fade2d0a..e4cb34cba1e6bcbd2e58f8a570258a372e2ea623 100644 --- a/rust-bins/duniter-dbex/Cargo.toml +++ b/rust-bins/duniter-dbex/Cargo.toml @@ -25,7 +25,8 @@ dirs = "3.0.1" dubp = { version = "0.32.2" } 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"] } -fast-threadpool = "0.2.1" +duniter-gva-db-writer = { path = "../../rust-libs/modules/gva/db-writer" } +fast-threadpool = "0.2.2" rayon = "1.3.1" serde_json = "1.0.53" structopt = "0.3.16" diff --git a/rust-bins/duniter-dbex/src/migrate.rs b/rust-bins/duniter-dbex/src/migrate.rs index 2e7b671d8cd2049995edc8e33c590472c8063597..149791a136fd1bd2c88c90ced9a68e166af5a3e3 100644 --- a/rust-bins/duniter-dbex/src/migrate.rs +++ b/rust-bins/duniter-dbex/src/migrate.rs @@ -18,9 +18,9 @@ use dubp::{ block::parser::parse_json_block_from_serde_value, block::parser::ParseJsonBlockError, block::prelude::DubpBlockTrait, block::DubpBlock, common::prelude::BlockNumber, }; -use duniter_dbs::BcV1DbReadable; +use duniter_dbs::{BcV1DbReadable, FileBackend}; use fast_threadpool::{ThreadPool, ThreadPoolConfig}; -use std::path::PathBuf; +use std::{ops::Deref, path::PathBuf}; const CHUNK_SIZE: usize = 250; @@ -32,6 +32,22 @@ pub(crate) fn migrate(profile_path: PathBuf) -> anyhow::Result<()> { dbs.bc_db.clear()?; dbs.gva_db.clear()?; + if let Err(e) = migrate_inner(dbs.clone(), profile_path, start_time) { + // Clear bc_db and gva_db + dbs.bc_db.clear()?; + dbs.gva_db.clear()?; + + Err(e) + } else { + Ok(()) + } +} + +fn migrate_inner( + dbs: DuniterDbs<FileBackend>, + profile_path: PathBuf, + start_time: Instant, +) -> anyhow::Result<()> { let data_path = profile_path.join(crate::DATA_DIR); let duniter_js_db = BcV1Db::<LevelDb>::open(LevelDbConf { db_path: data_path.as_path().join("leveldb"), @@ -94,9 +110,22 @@ pub(crate) fn migrate(profile_path: PathBuf) -> anyhow::Result<()> { chunk[0].number(), chunk[chunk.len() - 1].number() ); + let chunk = Arc::from(chunk); + let chunk_arc_clone = Arc::clone(&chunk); + let gva_handle = dbs_pool + .launch(move |dbs| { + for block in chunk_arc_clone.deref() { + duniter_gva_db_writer::apply_block(block, &dbs.gva_db)?; + } + Ok::<_, KvError>(()) + }) + .expect("gva:apply_chunk: dbs pool disconnected"); current = Some(duniter_dbs_write_ops::apply_block::apply_chunk( - current, &dbs_pool, chunk, true, + current, &dbs_pool, chunk, )?); + gva_handle + .join() + .expect("gva:apply_chunk: dbs pool disconnected")?; } } diff --git a/rust-libs/duniter-dbs-write-ops/Cargo.toml b/rust-libs/duniter-dbs-write-ops/Cargo.toml index f2eba28e3563bfe248653150f88f5f61c0db4104..24ca7023c1b8619544ffc2d46c42b0e89b9e4fa8 100644 --- a/rust-libs/duniter-dbs-write-ops/Cargo.toml +++ b/rust-libs/duniter-dbs-write-ops/Cargo.toml @@ -15,7 +15,7 @@ path = "src/lib.rs" chrono = "0.4.19" dubp = { version = "0.32.2" } duniter-dbs = { path = "../duniter-dbs" } -fast-threadpool = "0.2.1" +fast-threadpool = "0.2.2" log = "0.4.11" resiter = "0.4.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 fea9f164bc350d8e491714e25c5f60abae5ecb7d..216b9354a144a700e35082a30602c85b463daa2e 100644 --- a/rust-libs/duniter-dbs-write-ops/src/apply_block.rs +++ b/rust-libs/duniter-dbs-write-ops/src/apply_block.rs @@ -16,15 +16,14 @@ use crate::*; pub fn apply_block( - block: DubpBlockV10, + block: Arc<DubpBlockV10>, current_opt: Option<BlockMetaV2>, dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, - gva: bool, throw_chainability: bool, ) -> KvResult<BlockMetaV2> { if let Some(current) = current_opt { if block.number().0 == current.number + 1 { - apply_block_inner(dbs_pool, Arc::new(block), gva) + apply_block_inner(dbs_pool, block) } else if throw_chainability { Err(KvError::Custom( format!( @@ -38,7 +37,7 @@ pub fn apply_block( Ok(current) } } else if block.number() == BlockNumber(0) { - apply_block_inner(dbs_pool, Arc::new(block), gva) + apply_block_inner(dbs_pool, block) } else { Err(KvError::Custom( "Try to apply non genesis block on empty blockchain".into(), @@ -50,11 +49,10 @@ pub fn apply_block( pub fn apply_chunk( current_opt: Option<BlockMetaV2>, dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, - blocks: Vec<DubpBlockV10>, - gva: bool, + blocks: Arc<[DubpBlockV10]>, ) -> KvResult<BlockMetaV2> { verify_chunk_chainability(current_opt, &blocks)?; - apply_chunk_inner(dbs_pool, Arc::new(blocks), gva) + apply_chunk_inner(dbs_pool, blocks) } fn verify_chunk_chainability( @@ -104,7 +102,6 @@ fn verify_chunk_chainability( fn apply_block_inner( dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, block: Arc<DubpBlockV10>, - gva: bool, ) -> KvResult<BlockMetaV2> { // Bc let block_arc = Arc::clone(&block); @@ -119,24 +116,14 @@ fn apply_block_inner( Ok::<_, KvError>(()) }) .expect("dbs pool disconnected"); - // Gva - if gva { - let block_arc = Arc::clone(&block); - dbs_pool - .execute(move |dbs| { - crate::gva::apply_block(&block_arc, &dbs.gva_db)?; - Ok::<_, KvError>(()) - }) - .expect("dbs pool disconnected")?; - } + txs_mp_recv.join().expect("dbs pool disconnected")?; bc_recv.join().expect("dbs pool disconnected") } fn apply_chunk_inner( dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, - blocks: Arc<Vec<DubpBlockV10>>, - gva: bool, + blocks: Arc<[DubpBlockV10]>, ) -> KvResult<BlockMetaV2> { // Bc let blocks_len = blocks.len(); @@ -161,20 +148,6 @@ fn apply_chunk_inner( Ok::<_, KvError>(()) }) .expect("apply_chunk_inner:txs_mp: dbs pool disconnected"); - // Gva - if gva { - let blocks_arc = Arc::clone(&blocks); - //log::info!("apply_chunk: launch gva job..."); - dbs_pool - .execute(move |dbs| { - for block in blocks_arc.deref() { - crate::gva::apply_block(&block, &dbs.gva_db)?; - } - Ok::<_, KvError>(()) - }) - .expect("apply_chunk_inner:gva: dbs pool disconnected")?; - //log::info!("apply_chunk: gva job finish."); - } txs_mp_handle .join() .expect("txs_mp_recv: dbs pool disconnected")?; diff --git a/rust-libs/duniter-dbs-write-ops/src/bc.rs b/rust-libs/duniter-dbs-write-ops/src/bc.rs index 7bf65776c34a33f0c4bf363a3ae5d12025b713f8..47d573c5d718259ebd91ca4decd3747e3bff1fd9 100644 --- a/rust-libs/duniter-dbs-write-ops/src/bc.rs +++ b/rust-libs/duniter-dbs-write-ops/src/bc.rs @@ -85,7 +85,7 @@ pub fn apply_block<B: Backend>( pub fn revert_block<B: Backend>( bc_db: &duniter_dbs::bc_v2::BcV2Db<B>, - block: DubpBlockV10, + block: &DubpBlockV10, ) -> KvResult<Option<BlockMetaV2>> { ( bc_db.blocks_meta_write(), diff --git a/rust-libs/duniter-dbs-write-ops/src/lib.rs b/rust-libs/duniter-dbs-write-ops/src/lib.rs index 58a0a10662d2ac5492d7f8e4dcffe88b66577d70..d97f5c75fb493d8a6015969521ce0298f40e9e82 100644 --- a/rust-libs/duniter-dbs-write-ops/src/lib.rs +++ b/rust-libs/duniter-dbs-write-ops/src/lib.rs @@ -24,7 +24,6 @@ pub mod apply_block; pub mod bc; -pub mod gva; pub mod txs_mp; use std::borrow::Cow; @@ -37,157 +36,12 @@ use dubp::documents::{ transaction::TransactionDocumentV10, }; use dubp::wallet::prelude::*; -use duniter_dbs::gva_v1::{TxsByIssuerEvent, TxsByRecipientEvent, TxsEvent}; use duniter_dbs::{ - kv_typed::prelude::*, BlockMetaV2, DuniterDbs, FileBackend, GvaV1Db, GvaV1DbReadable, - GvaV1DbWritable, HashKeyV2, PendingTxDbV2, PubKeyKeyV2, PubKeyValV2, SourceAmountValV2, TxDbV2, - TxsMpV2Db, TxsMpV2DbReadable, TxsMpV2DbWritable, UtxoValV2, WalletConditionsV2, + kv_typed::prelude::*, BlockMetaV2, DuniterDbs, FileBackend, HashKeyV2, PendingTxDbV2, + PubKeyKeyV2, PubKeyValV2, SourceAmountValV2, TxsMpV2Db, TxsMpV2DbReadable, TxsMpV2DbWritable, + UtxoValV2, WalletConditionsV2, }; -use resiter::filter::Filter; use resiter::filter_map::FilterMap; use resiter::flatten::Flatten; use resiter::map::Map; -use std::{collections::HashMap, ops::Deref}; - -pub struct UtxoV10<'s> { - pub id: UtxoIdV10, - pub amount: SourceAmount, - pub script: &'s WalletScriptV10, - pub written_block: BlockNumber, -} - -#[cfg(test)] -mod tests { - use super::*; - use dubp::{ - documents::transaction::TransactionDocumentV10Stringified, - documents_parser::prelude::FromStringObject, - }; - - #[test] - #[ignore] - fn tmp_apply_block_real() -> KvResult<()> { - let gva_db = GvaV1Db::<Sled>::open( - SledConf::default() - .path("/home/elois/.config/duniter/s2/data/gva_v1_sled") - .flush_every_ms(None), - )?; - /*let txs_mp_db = TxsMpV2Db::<Sled>::open( - SledConf::default() - .path("/home/elois/.config/duniter/s2/data/txs_mp_v2_sled") - .flush_every_ms(None), - )?;*/ - - let txs: Vec<TransactionDocumentV10Stringified> = serde_json::from_str(r#"[ - { - "version": 10, - "currency": "g1", - "comment": ". je me sens plus legere mm si....reste le bon toit a trouver dans un temps record ! Merci pour cet eclairage fort", - "locktime": 0, - "signatures": [ - "8t5vo+k5OvkyAd+L+J8g6MLpp/AP0qOQFcJvf+OPMEZaVnHH38YtCigo64unU9aCsb9zZc6UEc78ZrkQ/E2TCg==" - ], - "outputs": [ - "5000:0:SIG(5VYg9YHvLQuoky7EPyyk3cEfBUtB1GuAeJ6SiJ6c9wWe)", - "55:0:SIG(Ceq5Y6W5kjFkPrvcx5oAgugLMTwcEXyWgfn3P85TSj7x)" - ], - "inputs": [ - "1011:0:D:Ceq5Y6W5kjFkPrvcx5oAgugLMTwcEXyWgfn3P85TSj7x:296658", - "1011:0:D:Ceq5Y6W5kjFkPrvcx5oAgugLMTwcEXyWgfn3P85TSj7x:296936", - "1011:0:D:Ceq5Y6W5kjFkPrvcx5oAgugLMTwcEXyWgfn3P85TSj7x:297211", - "1011:0:D:Ceq5Y6W5kjFkPrvcx5oAgugLMTwcEXyWgfn3P85TSj7x:297489", - "1011:0:D:Ceq5Y6W5kjFkPrvcx5oAgugLMTwcEXyWgfn3P85TSj7x:297786" - ], - "unlocks": [ - "0:SIG(0)", - "1:SIG(0)", - "2:SIG(0)", - "3:SIG(0)", - "4:SIG(0)" - ], - "blockstamp": "304284-000003F738B9A5FC8F5D04B4B9746FD899B3A49367099BB2796E7EF976DCDABB", - "blockstampTime": 0, - "issuers": [ - "Ceq5Y6W5kjFkPrvcx5oAgugLMTwcEXyWgfn3P85TSj7x" - ], - "block_number": 0, - "time": 0 - }, - { - "version": 10, - "currency": "g1", - "comment": "Pour les places de cine et l expedition ..Merci", - "locktime": 0, - "signatures": [ - "VhzwAwsCr30XnetveS74QD2kJMYCQ89VZvyUBJM9DP/kd5KBqkF1c1HcKpJdHrfu2oq3JbSEIhEf/aLgnEdSCw==" - ], - "outputs": [ - "6000:0:SIG(jUPLL2BgY2QpheWEY3R13edV2Y4tvQMCXjJVM8PGDvyd)", - "10347:0:SIG(2CWxxkttvkGSUVZdaUZHiksNisDC3wJx32Y2NVAyeHez)" - ], - "inputs": [ - "347:0:T:4EA4D01422469ABA380F48A48254EB3F15606C12FE4CFF7E7D6EEB1FD9752DDB:1", - "16000:0:T:9A4DA56EF5F9B50D612D806BAE0886EB3033B4F166D2E96498DE16B83F39B59D:0" - ], - "unlocks": [ - "0:SIG(0)", - "1:SIG(0)" - ], - "blockstamp": "304284-000003F738B9A5FC8F5D04B4B9746FD899B3A49367099BB2796E7EF976DCDABB", - "blockstampTime": 0, - "issuers": [ - "2CWxxkttvkGSUVZdaUZHiksNisDC3wJx32Y2NVAyeHez" - ], - "block_number": 0, - "time": 0 - }, - { - "version": 10, - "currency": "g1", - "comment": "POur le sac a tarte merci", - "locktime": 0, - "signatures": [ - "721K4f+F9PgksoVDZgQTURJIO/DZUhQfAzXfBvYrFkgqHNNeBbcgGecFX63rPYjFvau+qg1Hmi0coL9z7r7EAQ==" - ], - "outputs": [ - "15000:0:SIG(KxyNK1k55PEA8eBjX1K4dLJr35gC2dwMwNFPHwvZFH4)", - "17668:0:SIG(4VQvVLT1R6upLuRk85A5eWTowqJwvkSMGQQZ9Hc4bqLg)" - ], - "inputs": [ - "1011:0:D:4VQvVLT1R6upLuRk85A5eWTowqJwvkSMGQQZ9Hc4bqLg:303924", - "1011:0:D:4VQvVLT1R6upLuRk85A5eWTowqJwvkSMGQQZ9Hc4bqLg:304212", - "10458:0:T:55113E18AB61603AD0FC24CD11ACBC96F9583FD0A5877055F17315E9613BBF7D:1", - "20188:0:T:937A0454C1A63B383FBB6D219B9312B0A36DFE19DA08076BD113F9D5D4FC903D:1" - ], - "unlocks": [ - "0:SIG(0)", - "1:SIG(0)", - "2:SIG(0)", - "3:SIG(0)" - ], - "blockstamp": "304284-000003F738B9A5FC8F5D04B4B9746FD899B3A49367099BB2796E7EF976DCDABB", - "blockstampTime": 0, - "issuers": [ - "4VQvVLT1R6upLuRk85A5eWTowqJwvkSMGQQZ9Hc4bqLg" - ], - "block_number": 0, - "time": 0 - } - ]"#).expect("wrong tx"); - - let block = DubpBlockV10Stringified { - number: 304286, - hash: Some( - "000001339AECF3CAB78B2B61776FB3819B800AB43923F4F8BD0F5AE47B7DEAB9".to_owned(), - ), - median_time: 1583862823, - transactions: txs, - ..Default::default() - }; - let block = DubpBlockV10::from_string_object(&block).expect("fail to parse block"); - - gva::apply_block(&block, &gva_db)?; - - Ok(()) - } -} +use std::ops::Deref; diff --git a/rust-libs/duniter-module/Cargo.toml b/rust-libs/duniter-module/Cargo.toml index b502dad2d646538a3efeac3fc58f526270b4a258..81e0f6d970b48aba432e5ec5e1df6a8ce728c6fc 100644 --- a/rust-libs/duniter-module/Cargo.toml +++ b/rust-libs/duniter-module/Cargo.toml @@ -12,7 +12,7 @@ dubp = { version = "0.32.2" } duniter-conf = { path = "../duniter-conf" } duniter-dbs = { path = "../duniter-dbs" } duniter-mempools = { path = "../duniter-mempools" } -fast-threadpool = "0.2.1" +fast-threadpool = "0.2.2" [dev-dependencies] duniter-dbs = { path = "../duniter-dbs", features = ["mem"] } diff --git a/rust-libs/duniter-module/src/lib.rs b/rust-libs/duniter-module/src/lib.rs index d9e3d1ca45ff91eb4f263068464bef13d08145c1..e16aa988dacecb0748577915354d6ec309737f8d 100644 --- a/rust-libs/duniter-module/src/lib.rs +++ b/rust-libs/duniter-module/src/lib.rs @@ -22,15 +22,44 @@ unused_import_braces )] +use dubp::block::DubpBlockV10; use duniter_conf::DuniterConf; -use duniter_dbs::{DuniterDbs, FileBackend}; +use duniter_dbs::{kv_typed::prelude::*, DuniterDbs, FileBackend}; use duniter_mempools::Mempools; +use fast_threadpool::{JoinHandle, ThreadPoolDisconnected}; use std::path::Path; pub type Endpoint = String; #[async_trait::async_trait] pub trait DuniterModule: 'static + Sized { + fn apply_block( + _block: Arc<DubpBlockV10>, + _conf: &duniter_conf::DuniterConf, + _dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + _profile_path_opt: Option<&Path>, + ) -> Result<Option<JoinHandle<KvResult<()>>>, ThreadPoolDisconnected> { + Ok(None) + } + + fn apply_chunk_of_blocks( + _blocks: Arc<[DubpBlockV10]>, + _conf: &duniter_conf::DuniterConf, + _dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + _profile_path_opt: Option<&Path>, + ) -> Result<Option<JoinHandle<KvResult<()>>>, ThreadPoolDisconnected> { + Ok(None) + } + + fn revert_block( + _block: Arc<DubpBlockV10>, + _conf: &duniter_conf::DuniterConf, + _dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + _profile_path_opt: Option<&Path>, + ) -> Result<Option<JoinHandle<KvResult<()>>>, ThreadPoolDisconnected> { + Ok(None) + } + fn init( conf: &DuniterConf, currency: &str, @@ -48,6 +77,57 @@ macro_rules! plug_duniter_modules { ([$($M:ty),*]) => { 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>>, + profile_path_opt: Option<&Path>, + ) -> KvResult<()> { + $( + let [<$M:snake>] = <$M>::apply_block(block.clone(), conf, dbs_pool, profile_path_opt).expect("thread pool disconnected"); + )* + $( + if let Some(join_handle) = [<$M:snake>] { + join_handle.join().expect("thread pool disconnected")?; + } + )* + Ok(()) + } + #[allow(dead_code)] + fn apply_chunk_of_blocks_modules( + blocks: Arc<[DubpBlockV10]>, + conf: &duniter_conf::DuniterConf, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + profile_path_opt: Option<&Path>, + ) -> KvResult<()> { + $( + let [<$M:snake>] = <$M>::apply_chunk_of_blocks(blocks.clone(), conf, dbs_pool, profile_path_opt).expect("thread pool disconnected"); + )* + $( + if let Some(join_handle) = [<$M:snake>] { + join_handle.join().expect("thread pool disconnected")?; + } + )* + Ok(()) + } + #[allow(dead_code)] + fn revert_block_modules( + block: Arc<DubpBlockV10>, + conf: &duniter_conf::DuniterConf, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + profile_path_opt: Option<&Path>, + ) -> KvResult<()> { + $( + let [<$M:snake>] = <$M>::revert_block(block.clone(), conf, dbs_pool, profile_path_opt).expect("thread pool disconnected"); + )* + $( + if let Some(join_handle) = [<$M:snake>] { + join_handle.join().expect("thread pool disconnected")?; + } + )* + Ok(()) + } async fn start_duniter_modules( conf: &DuniterConf, currency: String, diff --git a/rust-libs/duniter-server/Cargo.toml b/rust-libs/duniter-server/Cargo.toml index d491ff2aadd6b145025201485d93c0bb166e6011..001fb611333a9aa1181b5114d2f46be73d63d709 100644 --- a/rust-libs/duniter-server/Cargo.toml +++ b/rust-libs/duniter-server/Cargo.toml @@ -16,7 +16,7 @@ duniter-gva = { path = "../modules/gva" } duniter-gva-dbs-reader = { path = "../modules/gva/dbs-reader" } duniter-mempools = { path = "../duniter-mempools" } duniter-module = { path = "../duniter-module" } -fast-threadpool = "0.2.1" +fast-threadpool = "0.2.2" flume = "0.9.1" log = "0.4.11" paste = "1.0.2" diff --git a/rust-libs/duniter-server/src/lib.rs b/rust-libs/duniter-server/src/lib.rs index 93dbb28ab3fc0830cffd212a515ee8ed1ffdc085..1b9c6375def724c6a35acb5fa254dbf6e483ea04 100644 --- a/rust-libs/duniter-server/src/lib.rs +++ b/rust-libs/duniter-server/src/lib.rs @@ -257,49 +257,51 @@ impl DuniterServer { .expect("dbs pool disconnected") } pub fn revert_block(&mut self, block: DubpBlockV10Stringified) -> KvResult<()> { - let gva = self.conf.gva.is_some(); - let block = DubpBlockV10::from_string_object(&block) - .map_err(|e| KvError::DeserError(format!("{}", e)))?; + let block = Arc::new( + DubpBlockV10::from_string_object(&block) + .map_err(|e| KvError::DeserError(format!("{}", e)))?, + ); + let block_arc_clone = Arc::clone(&block); self.current = self .dbs_pool .execute(move |dbs| { - duniter_dbs_write_ops::txs_mp::revert_block(block.transactions(), &dbs.txs_mp_db)?; - if gva { - duniter_dbs_write_ops::gva::revert_block(&block, &dbs.gva_db)?; - } - duniter_dbs_write_ops::bc::revert_block(&dbs.bc_db, block) + duniter_dbs_write_ops::txs_mp::revert_block( + block_arc_clone.transactions(), + &dbs.txs_mp_db, + )?; + duniter_dbs_write_ops::bc::revert_block(&dbs.bc_db, &block_arc_clone) }) .expect("dbs pool disconnected")?; - Ok(()) + revert_block_modules(block, &self.conf, &self.dbs_pool, None) } pub fn apply_block(&mut self, block: DubpBlockV10Stringified) -> KvResult<()> { - let gva = self.conf.gva.is_some(); - let block = DubpBlockV10::from_string_object(&block) - .map_err(|e| KvError::DeserError(format!("{}", e)))?; + 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( - block, + block.clone(), self.current, &self.dbs_pool, - gva, false, )?); - Ok(()) + 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 gva = self.conf.gva.is_some(); - let blocks = blocks - .into_iter() - .map(|block| DubpBlockV10::from_string_object(&block)) - .collect::<Result<Vec<_>, _>>() - .map_err(|e| KvError::DeserError(format!("{}", e)))?; + 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.current, &self.dbs_pool, - blocks, - gva, + blocks.clone(), )?); - Ok(()) + apply_chunk_of_blocks_modules(blocks, &self.conf, &self.dbs_pool, None) } pub fn trim_expired_non_written_txs(&self, limit_time: i64) -> KvResult<()> { self.dbs_pool diff --git a/rust-libs/modules/gva/Cargo.toml b/rust-libs/modules/gva/Cargo.toml index 4d3cdbbc85dbcdef65dc76cb36bdaf5f9b2b2bdd..634f15c1e1375662f8aa8e8a823eb5e45c375f81 100644 --- a/rust-libs/modules/gva/Cargo.toml +++ b/rust-libs/modules/gva/Cargo.toml @@ -16,9 +16,10 @@ duniter-conf = { path = "../../duniter-conf" } duniter-dbs = { path = "../../duniter-dbs" } duniter-dbs-read-ops = { path = "../../duniter-dbs-read-ops" } duniter-gva-dbs-reader = { path = "./dbs-reader" } +duniter-gva-db-writer = { path = "./db-writer" } duniter-mempools = { path = "../../duniter-mempools" } duniter-module = { path = "../../duniter-module" } -fast-threadpool = "0.2.1" +fast-threadpool = "0.2.2" flume = "0.9.1" futures = "0.3.6" http = "0.2.1" diff --git a/rust-libs/modules/gva/db-writer/Cargo.toml b/rust-libs/modules/gva/db-writer/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..8778c3910c4cb7cdbe9ec516335d7371b01806c7 --- /dev/null +++ b/rust-libs/modules/gva/db-writer/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "duniter-gva-db-writer" +version = "0.1.0" +authors = ["elois <elois@duniter.org>"] +description = "Duniter GVA DB writer" +repository = "https://git.duniter.org/nodes/typescript/duniter" +keywords = ["dubp", "duniter", "blockchain", "database"] +license = "AGPL-3.0" +edition = "2018" + +[lib] +path = "src/lib.rs" + +[dependencies] +anyhow = "1.0.34" +duniter-dbs = { path = "../../../duniter-dbs" } +dubp = { version = "0.32.2" } +resiter = "0.4.0" + +[dev-dependencies] +smallvec = { version = "1.4.0", features = ["serde", "write"] } diff --git a/rust-libs/duniter-dbs-write-ops/src/gva/identities.rs b/rust-libs/modules/gva/db-writer/src/identities.rs similarity index 100% rename from rust-libs/duniter-dbs-write-ops/src/gva/identities.rs rename to rust-libs/modules/gva/db-writer/src/identities.rs diff --git a/rust-libs/duniter-dbs-write-ops/src/gva.rs b/rust-libs/modules/gva/db-writer/src/lib.rs similarity index 94% rename from rust-libs/duniter-dbs-write-ops/src/gva.rs rename to rust-libs/modules/gva/db-writer/src/lib.rs index cff8a25635c793ae4c4e7a2565773dcdcb419998..6346c5bb42d26da60f1e336661c42ce940b07296 100644 --- a/rust-libs/duniter-dbs-write-ops/src/gva.rs +++ b/rust-libs/modules/gva/db-writer/src/lib.rs @@ -13,12 +13,40 @@ // 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/>. +#![deny( + clippy::unwrap_used, + missing_copy_implementations, + trivial_casts, + trivial_numeric_casts, + unstable_features, + unused_import_braces +)] + mod identities; mod tx; mod utxos; -use crate::*; -use duniter_dbs::gva_v1::{BalancesEvent, GvaIdentitiesEvent}; +use dubp::block::prelude::*; +use dubp::common::crypto::hashs::Hash; +use dubp::common::prelude::*; +use dubp::documents::{ + prelude::*, transaction::TransactionDocumentTrait, transaction::TransactionDocumentV10, +}; +use dubp::wallet::prelude::*; +use duniter_dbs::gva_v1::*; +use duniter_dbs::{ + kv_typed::prelude::*, GvaV1Db, GvaV1DbReadable, GvaV1DbWritable, HashKeyV2, PubKeyKeyV2, + SourceAmountValV2, TxDbV2, WalletConditionsV2, +}; +use resiter::filter::Filter; +use std::collections::HashMap; + +pub struct UtxoV10<'s> { + pub id: UtxoIdV10, + pub amount: SourceAmount, + pub script: &'s WalletScriptV10, + pub written_block: BlockNumber, +} pub fn apply_block<B: Backend>(block: &DubpBlockV10, gva_db: &GvaV1Db<B>) -> KvResult<()> { let blockstamp = Blockstamp { diff --git a/rust-libs/duniter-dbs-write-ops/src/gva/tx.rs b/rust-libs/modules/gva/db-writer/src/tx.rs similarity index 99% rename from rust-libs/duniter-dbs-write-ops/src/gva/tx.rs rename to rust-libs/modules/gva/db-writer/src/tx.rs index 7c00db023893180eec42047a02de1dc2deb81778..73314585755bf1761052ecba1c7780c76df0f524 100644 --- a/rust-libs/duniter-dbs-write-ops/src/gva/tx.rs +++ b/rust-libs/modules/gva/db-writer/src/tx.rs @@ -312,6 +312,7 @@ mod tests { documents::smallvec::smallvec as svec, documents::transaction::v10::*, documents::transaction::UTXOConditions, }; + use duniter_dbs::BlockMetaV2; #[test] fn test_apply_tx() -> KvResult<()> { diff --git a/rust-libs/duniter-dbs-write-ops/src/gva/utxos.rs b/rust-libs/modules/gva/db-writer/src/utxos.rs similarity index 100% rename from rust-libs/duniter-dbs-write-ops/src/gva/utxos.rs rename to rust-libs/modules/gva/db-writer/src/utxos.rs diff --git a/rust-libs/modules/gva/src/lib.rs b/rust-libs/modules/gva/src/lib.rs index 374371fdaac6fc057acccafda28002a22cb729fd..5bcd84c4c8756485c41433e0d20ad2e3205ed72d 100644 --- a/rust-libs/modules/gva/src/lib.rs +++ b/rust-libs/modules/gva/src/lib.rs @@ -50,6 +50,7 @@ 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::*; @@ -63,11 +64,13 @@ use duniter_gva_dbs_reader::create_dbs_reader; #[cfg(not(test))] use duniter_gva_dbs_reader::DbsReader; use duniter_mempools::{Mempools, TxsMempool}; +use fast_threadpool::{JoinHandle, ThreadPoolDisconnected}; use futures::{StreamExt, TryStreamExt}; use resiter::map::Map; use std::{ convert::{Infallible, TryFrom}, ops::Deref, + path::Path, }; use warp::{http::Response as HttpResponse, Filter as _, Rejection, Stream}; @@ -83,6 +86,51 @@ pub struct GvaModule { #[async_trait::async_trait] 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>, + ) -> Result<Option<JoinHandle<KvResult<()>>>, ThreadPoolDisconnected> { + if conf.gva.is_some() { + Ok(Some(dbs_pool.launch(move |dbs| { + duniter_gva_db_writer::apply_block(&block, &dbs.gva_db) + })?)) + } else { + Ok(None) + } + } + fn apply_chunk_of_blocks( + blocks: Arc<[DubpBlockV10]>, + conf: &duniter_conf::DuniterConf, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + _profile_path_opt: Option<&Path>, + ) -> Result<Option<JoinHandle<KvResult<()>>>, ThreadPoolDisconnected> { + if conf.gva.is_some() { + Ok(Some(dbs_pool.launch(move |dbs| { + for block in blocks.deref() { + duniter_gva_db_writer::apply_block(&block, &dbs.gva_db)?; + } + Ok::<_, KvError>(()) + })?)) + } else { + Ok(None) + } + } + fn revert_block( + block: Arc<DubpBlockV10>, + conf: &duniter_conf::DuniterConf, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, + _profile_path_opt: Option<&Path>, + ) -> Result<Option<JoinHandle<KvResult<()>>>, ThreadPoolDisconnected> { + if conf.gva.is_some() { + Ok(Some(dbs_pool.launch(move |dbs| { + duniter_gva_db_writer::revert_block(&block, &dbs.gva_db) + })?)) + } else { + Ok(None) + } + } fn init( conf: &duniter_conf::DuniterConf, currency: &str, diff --git a/rust-libs/tests/duniter-integration-tests/Cargo.toml b/rust-libs/tests/duniter-integration-tests/Cargo.toml index ed2bea409ede9752db951d13b601fefa9ac760f8..7bf61496a8f5e7bcdc060161691fa7b4172b1872 100644 --- a/rust-libs/tests/duniter-integration-tests/Cargo.toml +++ b/rust-libs/tests/duniter-integration-tests/Cargo.toml @@ -16,7 +16,7 @@ duniter-gva = { path = "../../modules/gva" } duniter-mempools = { path = "../../duniter-mempools" } duniter-module = { path = "../../duniter-module" } duniter-server = { path = "../../duniter-server" } -fast-threadpool = "0.2.1" +fast-threadpool = "0.2.2" flume = "0.9.1" log = "0.4.11" paste = "1.0.2"