diff --git a/Cargo.lock b/Cargo.lock index a8e8112d3a50e773bdb65f1561e2d29cfbf49b21..bea864b280641d246b2d9a55f79345b04a3fee05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -958,9 +958,9 @@ checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" [[package]] name = "dubp" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2a6192b0248f4b198e9193a59ee73e26ee2feba9b7c4995e628d11d2c19448a" +checksum = "362f2f4944b4c83949cfe91a3c2cf357d45e484ad93719a72a823e4a8e9f57c4" dependencies = [ "dubp-block", "dubp-common", @@ -972,9 +972,9 @@ dependencies = [ [[package]] name = "dubp-block" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f59b0253ba66aee87741603f20bab7d67e2ebe11f2bbff58bbc08486b132bb2" +checksum = "02bf4bd694cb294032e23b8a4dd7f33e69c16cf0cc43d0cea930ea6ec05c17b0" dependencies = [ "dubp-documents", "dubp-documents-parser", @@ -987,9 +987,9 @@ dependencies = [ [[package]] name = "dubp-common" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a927b5f18b8d5f04b6d1ca179a5678f5f559140844268f78c6872d20fd6f6178" +checksum = "fa7ad811ff15659e90561b028ff7cdf57b8e05cf647a421f7014202722567a82" dependencies = [ "dup-crypto", "serde", @@ -1000,9 +1000,9 @@ dependencies = [ [[package]] name = "dubp-documents" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ccce9aabcb92de2befbbd4360fc73d806df63dce414274bef427de2a7acb725" +checksum = "42a01990f2234f853e8768e5403ec89e02afea47760e3644fe59153558d328d9" dependencies = [ "beef", "dubp-wallet", @@ -1014,9 +1014,9 @@ dependencies = [ [[package]] name = "dubp-documents-parser" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abaa735586c05cc4cd1f240eb9531a9762d97e0f55a335e6e11658f4b10f29af" +checksum = "d7221d36592e369527a832f1f4b5fa3ff11e7d68467a2384d1d5fc6d7728159d" dependencies = [ "dubp-documents", "json-pest-parser", @@ -1028,9 +1028,9 @@ dependencies = [ [[package]] name = "dubp-wallet" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b73e3ae439e2eba8048ca9830a821cd6cbb51010e0049efc72e201433e6a61d" +checksum = "1e9ef70cc701226d3610452284637f0c86412f5d1a5831f6147964a23366e409" dependencies = [ "byteorder", "dubp-common", @@ -1124,6 +1124,7 @@ dependencies = [ "duniter-dbs", "fast-threadpool", "log", + "maplit", "resiter", "serde_json", ] @@ -1292,9 +1293,9 @@ dependencies = [ [[package]] name = "dup-crypto" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e577ae936c53b85818749d1eefedf1d1afd6e0a8286b88543cb068396c16069" +checksum = "2e1f1a33a3c3c66c0f2e1e050e2dbd8291975308eac2f7a1a58732f58a21c2e5" dependencies = [ "base64", "bs58", diff --git a/neon/native/Cargo.toml b/neon/native/Cargo.toml index 569c57566f66f1602be278f5ff7a0e5e5e15d058..90daffb97f10896e1c7c93b6282cba5abebd15eb 100644 --- a/neon/native/Cargo.toml +++ b/neon/native/Cargo.toml @@ -17,7 +17,7 @@ neon-build = "0.4.0" [dependencies] bincode = "1.2.1" bs58 = "0.3.0" -dubp = { version = "0.33.0" } +dubp = { version = "0.34.0" } dubp-wot = { path = "../../rust-libs/dubp-wot" } duniter-server = { path = "../../rust-libs/duniter-server" } flate2 = "1.0.16" diff --git a/rust-bins/duniter-dbex/Cargo.toml b/rust-bins/duniter-dbex/Cargo.toml index ec9a940846e2423dcd66bb12472cdd1e5197557a..23439503c80327d1db5ef8e5c0bdd6ac17339eb9 100644 --- a/rust-bins/duniter-dbex/Cargo.toml +++ b/rust-bins/duniter-dbex/Cargo.toml @@ -22,7 +22,7 @@ anyhow = "1.0.33" arrayvec = "0.5.1" comfy-table = "1.0.0" dirs = "3.0.1" -dubp = { version = "0.33.0" } +dubp = { version = "0.34.0" } 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" } diff --git a/rust-libs/duniter-conf/Cargo.toml b/rust-libs/duniter-conf/Cargo.toml index 86b76c3a50053786f372914b9edc5f679a79bc2d..860f3992b329b64a409fb67e9457f5356fc7266b 100644 --- a/rust-libs/duniter-conf/Cargo.toml +++ b/rust-libs/duniter-conf/Cargo.toml @@ -6,5 +6,5 @@ license = "AGPL-3.0" edition = "2018" [dependencies] -dubp = { version = "0.33.0" } +dubp = { version = "0.34.0" } serde = { version = "1.0.105", features = ["derive"] } diff --git a/rust-libs/duniter-dbs-read-ops/Cargo.toml b/rust-libs/duniter-dbs-read-ops/Cargo.toml index 908c5339c73bd43396304308ddc871932ed3ae97..7a64e8b667842390324484c1d4cbe845e3959d4b 100644 --- a/rust-libs/duniter-dbs-read-ops/Cargo.toml +++ b/rust-libs/duniter-dbs-read-ops/Cargo.toml @@ -14,7 +14,7 @@ path = "src/lib.rs" [dependencies] anyhow = "1.0.34" duniter-dbs = { path = "../duniter-dbs" } -dubp = { version = "0.33.0" } +dubp = { version = "0.34.0" } resiter = "0.4.0" [dev-dependencies] diff --git a/rust-libs/duniter-dbs-write-ops/Cargo.toml b/rust-libs/duniter-dbs-write-ops/Cargo.toml index 387bc8c97a597fc17be7f85dc642efabd9eec316..6696ec08afada6fcbd639898e714170355434b61 100644 --- a/rust-libs/duniter-dbs-write-ops/Cargo.toml +++ b/rust-libs/duniter-dbs-write-ops/Cargo.toml @@ -13,7 +13,7 @@ path = "src/lib.rs" [dependencies] chrono = "0.4.19" -dubp = { version = "0.33.0" } +dubp = { version = "0.34.0" } duniter-dbs = { path = "../duniter-dbs" } fast-threadpool = "0.2.2" log = "0.4.11" @@ -22,6 +22,7 @@ resiter = "0.4.0" [dev-dependencies] anyhow = "1.0.34" duniter-dbs = { path = "../duniter-dbs", features = ["mem"] } +maplit = "1.0.2" serde_json = "1.0.53" [features] diff --git a/rust-libs/duniter-dbs-write-ops/src/bc.rs b/rust-libs/duniter-dbs-write-ops/src/bc.rs index 013700b96552773f1b020ebf40bef43d5b551d72..7d236d05a6f30e4a5e900b0624051ece9a4d563a 100644 --- a/rust-libs/duniter-dbs-write-ops/src/bc.rs +++ b/rust-libs/duniter-dbs-write-ops/src/bc.rs @@ -55,6 +55,8 @@ pub fn apply_block<B: Backend>( bc_db.uds_write(), bc_db.uds_reval_write(), bc_db.uids_index_write(), + bc_db.utxos_write(), + bc_db.consumed_utxos_write(), ) .write( |( @@ -64,6 +66,8 @@ pub fn apply_block<B: Backend>( mut uds, mut uds_reval, mut uids_index, + mut utxos, + mut consumed_utxos, )| { blocks_meta.upsert(U32BE(block.number().0), block_meta); identities::update_identities::<B>(&block, &mut identities)?; @@ -81,14 +85,35 @@ pub fn apply_block<B: Backend>( &mut uds_reval, )?; } - txs::apply_txs::<B>(block.transactions(), &mut txs_hashs, &mut uds)?; + txs::apply_txs::<B>( + block.number(), + block.transactions(), + &mut txs_hashs, + &mut uds, + &mut utxos, + &mut consumed_utxos, + )?; Ok(()) }, )?; + if block_meta.number > ROLL_BACK_MAX { + prune_bc_db(bc_db, BlockNumber(block_meta.number))?; + } + Ok(block_meta) } +fn prune_bc_db<B: Backend>( + bc_db: &duniter_dbs::databases::bc_v2::BcV2Db<B>, + current_block_number: BlockNumber, +) -> KvResult<()> { + bc_db + .consumed_utxos_write() + .remove(U32BE(current_block_number.0 - ROLL_BACK_MAX))?; + Ok(()) +} + pub fn revert_block<B: Backend>( bc_db: &duniter_dbs::databases::bc_v2::BcV2Db<B>, block: &DubpBlockV10, @@ -100,6 +125,8 @@ pub fn revert_block<B: Backend>( bc_db.uds_write(), bc_db.uds_reval_write(), bc_db.uids_index_write(), + bc_db.utxos_write(), + bc_db.consumed_utxos_write(), ) .write( |( @@ -109,8 +136,17 @@ pub fn revert_block<B: Backend>( mut uds, mut uds_reval, mut uids_index, + mut utxos, + mut consumed_utxos, )| { - txs::revert_txs::<B>(block.transactions(), &mut txs_hashs, &mut uds)?; + txs::revert_txs::<B>( + block.number(), + block.transactions(), + &mut txs_hashs, + &mut uds, + &mut utxos, + &mut consumed_utxos, + )?; if block.dividend().is_some() { uds::revert_uds::<B>( block.number(), @@ -133,3 +169,177 @@ pub fn revert_block<B: Backend>( }, ) } + +#[cfg(test)] +mod tests { + use super::*; + use dubp::{ + crypto::keys::PublicKey as _, documents::transaction::TransactionDocumentV10Stringified, + documents_parser::prelude::FromStringObject, + }; + use duniter_dbs::{ + databases::bc_v2::*, BlockUtxosV2Db, UtxoIdDbV2, WalletScriptWithSourceAmountV1Db, + }; + use maplit::hashmap; + + #[test] + fn test_bc_apply_block() -> anyhow::Result<()> { + let bc_db = BcV2Db::<Mem>::open(MemConf::default())?; + + let s1 = WalletScriptV10::single_sig(PublicKey::from_base58( + "D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx", + )?); + let s2 = WalletScriptV10::single_sig(PublicKey::from_base58( + "4fHMTFBMo5sTQEc5p1CNWz28S4mnnqdUBmECq1zt4n2m", + )?); + + let b0 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { + version: 10, + median_time: 5_243, + dividend: Some(1000), + joiners: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:FFeyrvYio9uYwY5aMcDGswZPNjGLrl8THn9l3EPKSNySD3SDSHjCljSfFEwb87sroyzJQoVzPwER0sW/cbZMDg==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:elois".to_owned()], + inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), + signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), + hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), + ..Default::default() + })?; + + apply_block(&bc_db, &b0)?; + + assert_eq!(bc_db.blocks_meta().count()?, 1); + assert_eq!(bc_db.uds().count()?, 1); + assert_eq!(bc_db.utxos().count()?, 0); + assert_eq!(bc_db.consumed_utxos().count()?, 0); + + let b1 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { + number: 1, + version: 10, + median_time: 5_245, + transactions: vec![TransactionDocumentV10Stringified { + currency: "test".to_owned(), + blockstamp: "0-0000000000000000000000000000000000000000000000000000000000000000".to_owned(), + locktime: 0, + issuers: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx".to_owned()], + inputs: vec!["1000:0:D:D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:0".to_owned()], + unlocks: vec![], + outputs: vec![ + "600:0:SIG(4fHMTFBMo5sTQEc5p1CNWz28S4mnnqdUBmECq1zt4n2m)".to_owned(), + "400:0:SIG(D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx)".to_owned(), + ], + comment: "".to_owned(), + signatures: vec![], + hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), + }], + inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), + signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), + hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), + ..Default::default() + })?; + + apply_block(&bc_db, &b1)?; + + assert_eq!(bc_db.blocks_meta().count()?, 2); + assert_eq!(bc_db.uds().count()?, 0); + assert_eq!(bc_db.utxos().count()?, 2); + assert_eq!( + bc_db + .utxos() + .iter(.., |it| it.collect::<KvResult<Vec<_>>>())?, + vec![ + ( + UtxoIdDbV2(Hash::default(), 0), + WalletScriptWithSourceAmountV1Db { + wallet_script: s2.clone(), + source_amount: SourceAmount::with_base0(600) + } + ), + ( + UtxoIdDbV2(Hash::default(), 1), + WalletScriptWithSourceAmountV1Db { + wallet_script: s1.clone(), + source_amount: SourceAmount::with_base0(400) + } + ) + ] + ); + assert_eq!(bc_db.consumed_utxos().count()?, 0); + + let b2 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { + number: 2, + version: 10, + median_time: 5_247, + transactions: vec![TransactionDocumentV10Stringified { + currency: "test".to_owned(), + blockstamp: "0-0000000000000000000000000000000000000000000000000000000000000000".to_owned(), + locktime: 0, + issuers: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx".to_owned()], + inputs: vec!["400:0:T:0000000000000000000000000000000000000000000000000000000000000000:1".to_owned()], + unlocks: vec![], + outputs: vec![ + "300:0:SIG(D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx)".to_owned(), + "100:0:SIG(4fHMTFBMo5sTQEc5p1CNWz28S4mnnqdUBmECq1zt4n2m)".to_owned(), + ], + comment: "".to_owned(), + signatures: vec![], + hash: Some("0101010101010101010101010101010101010101010101010101010101010101".to_owned()), + }], + inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), + signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), + hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), + ..Default::default() + })?; + + apply_block(&bc_db, &b2)?; + + assert_eq!(bc_db.blocks_meta().count()?, 3); + assert_eq!(bc_db.uds().count()?, 0); + assert_eq!(bc_db.utxos().count()?, 3); + assert_eq!(bc_db.consumed_utxos().count()?, 1); + + assert_eq!( + bc_db + .consumed_utxos() + .iter(.., |it| it.collect::<KvResult<Vec<_>>>())?, + vec![( + U32BE(2), + BlockUtxosV2Db( + hashmap![UtxoIdV10 { tx_hash: Hash::default(), output_index: 1 } => WalletScriptWithSourceAmountV1Db { + wallet_script: s1.clone(), + source_amount: SourceAmount::with_base0(400) + }] + ) + )] + ); + + assert_eq!( + bc_db + .utxos() + .iter(.., |it| it.collect::<KvResult<Vec<_>>>())?, + vec![ + ( + UtxoIdDbV2(Hash::default(), 0), + WalletScriptWithSourceAmountV1Db { + wallet_script: s2.clone(), + source_amount: SourceAmount::with_base0(600) + } + ), + ( + UtxoIdDbV2(Hash([1; 32]), 0), + WalletScriptWithSourceAmountV1Db { + wallet_script: s1, + source_amount: SourceAmount::with_base0(300) + } + ), + ( + UtxoIdDbV2(Hash([1; 32]), 1), + WalletScriptWithSourceAmountV1Db { + wallet_script: s2, + source_amount: SourceAmount::with_base0(100) + } + ) + ] + ); + + Ok(()) + } +} diff --git a/rust-libs/duniter-dbs-write-ops/src/bc/txs.rs b/rust-libs/duniter-dbs-write-ops/src/bc/txs.rs index 87b36acc78f41f6b5b240b0c22a7e9f89741d492..d8154fd0ca6f82f000096daaa0958d01601c4b6e 100644 --- a/rust-libs/duniter-dbs-write-ops/src/bc/txs.rs +++ b/rust-libs/duniter-dbs-write-ops/src/bc/txs.rs @@ -13,40 +13,105 @@ // 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 std::collections::HashMap; + use crate::*; +use dubp::documents::transaction::TransactionOutputV10; use duniter_dbs::{ - databases::bc_v2::{TxsHashsEvent, UdsEvent}, - UdIdV2, + databases::bc_v2::{ConsumedUtxosEvent, TxsHashsEvent, UdsEvent, UtxosEvent}, + BlockUtxosV2Db, UdIdV2, UtxoIdDbV2, WalletScriptWithSourceAmountV1Db, }; pub(crate) fn apply_txs<B: Backend>( + block_number: BlockNumber, block_txs: &[TransactionDocumentV10], txs_hashs: &mut TxColRw<B::Col, TxsHashsEvent>, uds: &mut TxColRw<B::Col, UdsEvent>, + utxos: &mut TxColRw<B::Col, UtxosEvent>, + consumed_utxos: &mut TxColRw<B::Col, ConsumedUtxosEvent>, ) -> KvResult<()> { - for tx in block_txs { - txs_hashs.upsert(HashKeyV2(tx.get_hash()), ()); - for input in tx.get_inputs() { - if let SourceIdV10::Ud(UdSourceIdV10 { - issuer, - block_number, - }) = input.id + if !block_txs.is_empty() { + let mut block_consumed_utxos = HashMap::with_capacity(block_txs.len() * 3); + for tx in block_txs { + let tx_hash = tx.get_hash(); + txs_hashs.upsert(HashKeyV2(tx_hash), ()); + for input in tx.get_inputs() { + match input.id { + SourceIdV10::Ud(UdSourceIdV10 { + issuer, + block_number, + }) => { + uds.remove(UdIdV2(issuer, block_number)); + } + SourceIdV10::Utxo(utxo_id) => { + let utxo_id_db = UtxoIdDbV2(utxo_id.tx_hash, utxo_id.output_index as u32); + if let Some(wallet_script_with_sa) = utxos.get(&utxo_id_db)? { + utxos.remove(utxo_id_db); + block_consumed_utxos.insert(utxo_id, wallet_script_with_sa); + } else { + return Err(KvError::Custom( + format!("db corrupted: not found utxo {:?}", utxo_id_db).into(), + )); + } + } + } + } + for (output_index, TransactionOutputV10 { amount, conditions }) in + tx.get_outputs().iter().enumerate() { - uds.remove(UdIdV2(issuer, block_number)); + let utxo_id = UtxoIdDbV2(tx_hash, output_index as u32); + let wallet_script_with_sa = WalletScriptWithSourceAmountV1Db { + wallet_script: conditions.script.clone(), + source_amount: *amount, + }; + utxos.upsert(utxo_id, wallet_script_with_sa); } } + if !block_consumed_utxos.is_empty() { + consumed_utxos.upsert(U32BE(block_number.0), BlockUtxosV2Db(block_consumed_utxos)); + } } Ok(()) } pub(crate) fn revert_txs<B: Backend>( + block_number: BlockNumber, block_txs: &[TransactionDocumentV10], txs_hashs: &mut TxColRw<B::Col, TxsHashsEvent>, uds: &mut TxColRw<B::Col, UdsEvent>, + utxos: &mut TxColRw<B::Col, UtxosEvent>, + consumed_utxos: &mut TxColRw<B::Col, ConsumedUtxosEvent>, ) -> KvResult<()> { for tx in block_txs { - txs_hashs.remove(HashKeyV2(tx.get_hash())); + let tx_hash = tx.get_hash(); + txs_hashs.remove(HashKeyV2(tx_hash)); for input in tx.get_inputs() { + match input.id { + SourceIdV10::Ud(UdSourceIdV10 { + issuer, + block_number, + }) => { + uds.upsert(UdIdV2(issuer, block_number), ()); + } + SourceIdV10::Utxo(utxo_id) => { + let utxo_id_db = UtxoIdDbV2(utxo_id.tx_hash, utxo_id.output_index as u32); + if let Some(block_utxos) = consumed_utxos.get(&U32BE(block_number.0))? { + if let Some(wallet_script_with_sa) = block_utxos.0.get(&utxo_id) { + utxos.upsert(utxo_id_db, wallet_script_with_sa.clone()); + } else { + return Err(KvError::Custom( + format!("db corrupted: not found consumed utxos {}", utxo_id) + .into(), + )); + } + } else { + return Err(KvError::Custom( + format!("db corrupted: not found consumed utxos {:?}", utxo_id_db) + .into(), + )); + } + } + } if let SourceIdV10::Ud(UdSourceIdV10 { issuer, block_number, @@ -55,6 +120,11 @@ pub(crate) fn revert_txs<B: Backend>( uds.upsert(UdIdV2(issuer, block_number), ()); } } + for output_index in 0..tx.get_outputs().len() { + let utxo_id = UtxoIdDbV2(tx_hash, output_index as u32); + utxos.remove(utxo_id); + } } + consumed_utxos.remove(U32BE(block_number.0)); Ok(()) } diff --git a/rust-libs/duniter-dbs-write-ops/src/lib.rs b/rust-libs/duniter-dbs-write-ops/src/lib.rs index 405a35a899dba4cabf3acff6d3d80e22a1528e4b..8ccb4d566cb6d897af151cf74009e832b62f955e 100644 --- a/rust-libs/duniter-dbs-write-ops/src/lib.rs +++ b/rust-libs/duniter-dbs-write-ops/src/lib.rs @@ -49,3 +49,5 @@ use resiter::filter_map::FilterMap; use resiter::flatten::Flatten; use resiter::map::Map; use std::ops::Deref; + +const ROLL_BACK_MAX: u32 = 100; diff --git a/rust-libs/duniter-dbs/Cargo.toml b/rust-libs/duniter-dbs/Cargo.toml index 813fd38fd28b22e9e5c872cd4b137f079e10df61..33b35cdb03263bcc3d8ca2a7ca46996ad9386f79 100644 --- a/rust-libs/duniter-dbs/Cargo.toml +++ b/rust-libs/duniter-dbs/Cargo.toml @@ -16,7 +16,7 @@ arrayvec = "0.5.1" bincode = "1.2.1" byteorder = "1.3.4" chrono = { version = "0.4.15", optional = true } -dubp = { version = "0.33.0" } +dubp = { version = "0.34.0" } kv_typed = { path = "../tools/kv_typed", default-features = false } log = "0.4.8" mockall = { version = "0.8.0", optional = true } diff --git a/rust-libs/duniter-dbs/src/databases/bc_v2.rs b/rust-libs/duniter-dbs/src/databases/bc_v2.rs index 81dae61f2981c47c1f07ab5d65d2097c90ea414a..c5256029671a892a8e1a676e32ccb85d7f44556a 100644 --- a/rust-libs/duniter-dbs/src/databases/bc_v2.rs +++ b/rust-libs/duniter-dbs/src/databases/bc_v2.rs @@ -24,5 +24,7 @@ db_schema!( ["uds", Uds, UdIdV2, ()], ["uds_reval", UdsReval, U32BE, SourceAmountValV2], ["uids_index", UidsIndex, String, PubKeyValV2], + ["utxos", Utxos, UtxoIdDbV2, WalletScriptWithSourceAmountV1Db], + ["consumed_utxos", ConsumedUtxos, U32BE, BlockUtxosV2Db], ] ); diff --git a/rust-libs/duniter-dbs/src/lib.rs b/rust-libs/duniter-dbs/src/lib.rs index 6ac199e37260abd7cf6d6099fd38ef15b8930f90..480936e7a82d02fb0129d4b5ccb509f4fcc8dfda 100644 --- a/rust-libs/duniter-dbs/src/lib.rs +++ b/rust-libs/duniter-dbs/src/lib.rs @@ -83,9 +83,10 @@ pub use values::sindex_db::{SIndexDBV1, SourceKeyArrayDbV1}; pub use values::source_amount::SourceAmountValV2; pub use values::tx_db::{PendingTxDbV2, TxDbV2}; pub use values::ud_entry_db::{ConsumedUdDbV1, UdAmountDbV1, UdEntryDbV1}; -pub use values::utxo::UtxoValV2; +pub use values::utxo::{BlockUtxosV2Db, UtxoValV2}; pub use values::wallet_db::WalletDbV1; pub use values::wallet_script_array::WalletScriptArrayV2; +pub use values::wallet_script_with_sa::WalletScriptWithSourceAmountV1Db; // Crate imports pub(crate) use arrayvec::{ArrayString, ArrayVec}; diff --git a/rust-libs/duniter-dbs/src/values.rs b/rust-libs/duniter-dbs/src/values.rs index 27a5ce4fa70dc8404ee320022e08bcb26ba191bc..5471d4da42dbb260c30ebaceda70bbf30d9bec9a 100644 --- a/rust-libs/duniter-dbs/src/values.rs +++ b/rust-libs/duniter-dbs/src/values.rs @@ -33,3 +33,4 @@ pub mod ud_entry_db; pub mod utxo; pub mod wallet_db; pub mod wallet_script_array; +pub mod wallet_script_with_sa; diff --git a/rust-libs/duniter-dbs/src/values/utxo.rs b/rust-libs/duniter-dbs/src/values/utxo.rs index f24ef57c2244bf06ff323e65a7b142f51448f2bb..bfbfd358b9e50d9a7420c21d1dd86071ff325329 100644 --- a/rust-libs/duniter-dbs/src/values/utxo.rs +++ b/rust-libs/duniter-dbs/src/values/utxo.rs @@ -14,7 +14,7 @@ // along with this program. If not, see <https://www.gnu.org/licenses/>. use crate::*; -use std::ops::Deref; +use std::{collections::HashMap, ops::Deref}; #[derive( Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, zerocopy::AsBytes, zerocopy::FromBytes, @@ -108,6 +108,39 @@ impl ExplorableValue for UtxoValV2 { } } +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +pub struct BlockUtxosV2Db(pub HashMap<UtxoIdV10, WalletScriptWithSourceAmountV1Db>); + +impl ValueAsBytes for BlockUtxosV2Db { + fn as_bytes<T, F: FnMut(&[u8]) -> KvResult<T>>(&self, mut f: F) -> KvResult<T> { + f(&bincode::serialize(&self).map_err(|e| KvError::DeserError(format!("{}", e)))?) + } +} + +impl kv_typed::prelude::FromBytes for BlockUtxosV2Db { + type Err = StringErr; + + fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { + Ok(bincode::deserialize(bytes).map_err(|e| StringErr(format!("{}", e)))?) + } +} + +impl ToDumpString for BlockUtxosV2Db { + fn to_dump_string(&self) -> String { + todo!() + } +} + +#[cfg(feature = "explorer")] +impl ExplorableValue for BlockUtxosV2Db { + fn from_explorer_str(_: &str) -> std::result::Result<Self, StringErr> { + unimplemented!() + } + fn to_explorer_json(&self) -> KvResult<serde_json::Value> { + Ok(serde_json::to_value(self).map_err(|e| KvError::DeserError(e.to_string()))?) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/rust-libs/duniter-dbs/src/values/wallet_script_with_sa.rs b/rust-libs/duniter-dbs/src/values/wallet_script_with_sa.rs new file mode 100644 index 0000000000000000000000000000000000000000..def12e5059ab48cdbf67a11caa9364e5e5e2fc1f --- /dev/null +++ b/rust-libs/duniter-dbs/src/values/wallet_script_with_sa.rs @@ -0,0 +1,52 @@ +// Copyright (C) 2020 Éloïs SANCHEZ. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +use crate::*; + +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +pub struct WalletScriptWithSourceAmountV1Db { + pub wallet_script: WalletScriptV10, + pub source_amount: SourceAmount, +} + +impl ValueAsBytes for WalletScriptWithSourceAmountV1Db { + fn as_bytes<T, F: FnMut(&[u8]) -> KvResult<T>>(&self, mut f: F) -> KvResult<T> { + f(&bincode::serialize(&self).map_err(|e| KvError::DeserError(format!("{}", e)))?) + } +} + +impl kv_typed::prelude::FromBytes for WalletScriptWithSourceAmountV1Db { + type Err = StringErr; + + fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { + Ok(bincode::deserialize(bytes).map_err(|e| StringErr(format!("{}", e)))?) + } +} + +impl ToDumpString for WalletScriptWithSourceAmountV1Db { + fn to_dump_string(&self) -> String { + todo!() + } +} + +#[cfg(feature = "explorer")] +impl ExplorableValue for WalletScriptWithSourceAmountV1Db { + fn from_explorer_str(_: &str) -> std::result::Result<Self, StringErr> { + unimplemented!() + } + fn to_explorer_json(&self) -> KvResult<serde_json::Value> { + Ok(serde_json::to_value(self).map_err(|e| KvError::DeserError(e.to_string()))?) + } +} diff --git a/rust-libs/duniter-mempools/Cargo.toml b/rust-libs/duniter-mempools/Cargo.toml index c5bacfe9581594d5eaaacc788da0d0dd56248946..bd43adfc51b49ee213df3f6ef888abe5f132db66 100644 --- a/rust-libs/duniter-mempools/Cargo.toml +++ b/rust-libs/duniter-mempools/Cargo.toml @@ -12,7 +12,7 @@ edition = "2018" path = "src/lib.rs" [dependencies] -dubp = { version = "0.33.0" } +dubp = { version = "0.34.0" } duniter-dbs = { path = "../duniter-dbs" } duniter-dbs-read-ops = { path = "../duniter-dbs-read-ops" } duniter-dbs-write-ops = { path = "../duniter-dbs-write-ops" } diff --git a/rust-libs/duniter-module/Cargo.toml b/rust-libs/duniter-module/Cargo.toml index a664eada89ac041861eb647ef6abfb166ff09e65..ae95637f8d9af7defc49a45a15b34e30d21cf960 100644 --- a/rust-libs/duniter-module/Cargo.toml +++ b/rust-libs/duniter-module/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" [dependencies] anyhow = "1.0.34" async-trait = "0.1.41" -dubp = { version = "0.33.0" } +dubp = { version = "0.34.0" } duniter-conf = { path = "../duniter-conf" } duniter-dbs = { path = "../duniter-dbs" } duniter-mempools = { path = "../duniter-mempools" } diff --git a/rust-libs/duniter-server/Cargo.toml b/rust-libs/duniter-server/Cargo.toml index 408ceeb1a5ac77bf560ade73dbabeb924223ce26..4d8f22b7a8ec5beec618c14468e2ca080d34afb6 100644 --- a/rust-libs/duniter-server/Cargo.toml +++ b/rust-libs/duniter-server/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" [dependencies] anyhow = "1.0.34" cfg-if = "1.0.0" -dubp = { version = "0.33.0" } +dubp = { version = "0.34.0" } duniter-conf = { path = "../duniter-conf" } duniter-dbs = { path = "../duniter-dbs" } duniter-dbs-read-ops = { path = "../duniter-dbs-read-ops" } diff --git a/rust-libs/modules/gva/Cargo.toml b/rust-libs/modules/gva/Cargo.toml index 965bf4c17511f88a9ae20625ae4de21b136586c3..5695a8cba0e3d18b9352e6ac4d304441dccedef4 100644 --- a/rust-libs/modules/gva/Cargo.toml +++ b/rust-libs/modules/gva/Cargo.toml @@ -11,7 +11,7 @@ arrayvec = "0.5.1" async-graphql = "2.0.0" async-mutex = "1.4.0" async-trait = "0.1.41" -dubp = { version = "0.33.0" } +dubp = { version = "0.34.0" } duniter-conf = { path = "../../duniter-conf" } duniter-dbs = { path = "../../duniter-dbs" } duniter-dbs-read-ops = { path = "../../duniter-dbs-read-ops" } diff --git a/rust-libs/modules/gva/db-writer/Cargo.toml b/rust-libs/modules/gva/db-writer/Cargo.toml index 424ae6146f438be7bb6740670e971510a886d3e5..801f2f15ba2534460de32e53870635094cdc4735 100644 --- a/rust-libs/modules/gva/db-writer/Cargo.toml +++ b/rust-libs/modules/gva/db-writer/Cargo.toml @@ -14,7 +14,7 @@ path = "src/lib.rs" [dependencies] anyhow = "1.0.34" duniter-dbs = { path = "../../../duniter-dbs" } -dubp = { version = "0.33.0" } +dubp = { version = "0.34.0" } resiter = "0.4.0" [dev-dependencies] diff --git a/rust-libs/modules/gva/dbs-reader/Cargo.toml b/rust-libs/modules/gva/dbs-reader/Cargo.toml index 78d4956b29adf9fa0622de59be1dcc61941f4fed..e83081ca3fc54e80515f9d1eba9c456a876358b9 100644 --- a/rust-libs/modules/gva/dbs-reader/Cargo.toml +++ b/rust-libs/modules/gva/dbs-reader/Cargo.toml @@ -14,7 +14,7 @@ path = "src/lib.rs" [dependencies] anyhow = "1.0.34" duniter-dbs = { path = "../../../duniter-dbs" } -dubp = { version = "0.33.0" } +dubp = { version = "0.34.0" } resiter = "0.4.0" [dev-dependencies] diff --git a/rust-libs/tests/duniter-integration-tests/Cargo.toml b/rust-libs/tests/duniter-integration-tests/Cargo.toml index 355a6a7aa53a9a558aff2928107c1dce567966c1..6016dd250d92aa73b94111298eb290867498ce02 100644 --- a/rust-libs/tests/duniter-integration-tests/Cargo.toml +++ b/rust-libs/tests/duniter-integration-tests/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] anyhow = "1.0.34" -dubp = { version = "0.33.0" } +dubp = { version = "0.34.0" } duniter-conf = { path = "../../duniter-conf" } duniter-dbs = { path = "../../duniter-dbs" } duniter-dbs-read-ops = { path = "../../duniter-dbs-read-ops" }