diff --git a/Cargo.lock b/Cargo.lock index aba7f23d79caa9092b4d5c85a0894699b90f41a8..5e089d160d7bf5a9daa2da383f688206bdfba7f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -745,25 +745,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" dependencies = [ "cfg-if 1.0.0", - "crossbeam-epoch 0.9.0", + "crossbeam-epoch", "crossbeam-utils 0.8.0", ] -[[package]] -name = "crossbeam-epoch" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" -dependencies = [ - "autocfg 1.0.1", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "lazy_static", - "maybe-uninit", - "memoffset", - "scopeguard", -] - [[package]] name = "crossbeam-epoch" version = "0.9.0" @@ -2156,12 +2141,6 @@ dependencies = [ "syn", ] -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "memchr" version = "2.3.3" @@ -3324,13 +3303,13 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "sled" -version = "0.34.4" +version = "0.34.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f72c064e63fbca3138ad07f3588c58093f1684f3a99f60dcfa6d46b87e60fde7" +checksum = "1d0132f3e393bcb7390c60bb45769498cf4550bcb7a21d7f95c02b69f6362cdc" dependencies = [ "crc32fast", - "crossbeam-epoch 0.8.2", - "crossbeam-utils 0.7.2", + "crossbeam-epoch", + "crossbeam-utils 0.8.0", "fs2", "fxhash", "libc", diff --git a/rust-libs/modules/gva/indexer/src/lib.rs b/rust-libs/modules/gva/indexer/src/lib.rs index 8e39e42d1373b8fe46f52f407319c76849ca0337..a7411f2d99ba713a2c2497dd9b134b069d1c2651 100644 --- a/rust-libs/modules/gva/indexer/src/lib.rs +++ b/rust-libs/modules/gva/indexer/src/lib.rs @@ -74,68 +74,58 @@ pub fn apply_block<B: Backend>(block: &DubpBlockV10, gva_db: &GvaV1Db<B>) -> KvR number: block.number(), hash: block.hash(), }; - ( - gva_db.balances_write(), - gva_db.blockchain_time_write(), - gva_db.blocks_with_ud_write(), - gva_db.gva_identities_write(), - ) - .write( - |(mut balances, mut blockchain_time, mut blocks_with_ud, mut gva_identities)| { - blockchain_time.upsert(U32BE(block.number().0), block.common_time()); - identities::update_identities::<B>(&block, &mut gva_identities)?; - if let Some(divident_amount) = block.dividend() { - blocks_with_ud.upsert(U32BE(blockstamp.number.0), ()); - apply_ud::<B>( - blockstamp.number, - divident_amount, - &mut balances, - &mut gva_identities, - )?; - } - Ok(()) - }, - )?; - apply_block_txs( - &gva_db, - blockstamp, - block.common_time() as i64, - block.transactions(), - )?; + gva_db.write(|mut db| { + db.blockchain_time + .upsert(U32BE(block.number().0), block.common_time()); + identities::update_identities::<B>(&block, &mut db.gva_identities)?; + if let Some(divident_amount) = block.dividend() { + db.blocks_with_ud.upsert(U32BE(blockstamp.number.0), ()); + apply_ud::<B>( + blockstamp.number, + divident_amount, + &mut db.balances, + &mut db.gva_identities, + )?; + } + apply_block_txs::<B>( + &mut db, + blockstamp, + block.common_time() as i64, + block.transactions(), + ) + })?; Ok(()) } pub fn revert_block<B: Backend>(block: &DubpBlockV10, gva_db: &GvaV1Db<B>) -> KvResult<()> { - ( - gva_db.balances_write(), - gva_db.blockchain_time_write(), - gva_db.blocks_with_ud_write(), - gva_db.gva_identities_write(), - ) - .write( - |(mut balances, mut blockchain_time, mut blocks_with_ud, mut gva_identities)| { - blockchain_time.remove(U32BE(block.number().0)); - identities::revert_identities::<B>(&block, &mut gva_identities)?; - if let Some(divident_amount) = block.dividend() { - blocks_with_ud.remove(U32BE(block.number().0)); - revert_ud::<B>( - block.number(), - divident_amount, - &mut balances, - &mut gva_identities, - )?; - } - Ok(()) - }, - )?; - let mut scripts_hash = HashMap::with_capacity(block.transactions().len() * 3); - for tx in block.transactions() { - let tx_hash = tx.get_hash(); - tx::revert_tx(block.number(), gva_db, &mut scripts_hash, &tx_hash)?.ok_or_else(|| { - KvError::DbCorrupted(format!("GVA: tx '{}' dont exist on txs history.", tx_hash,)) - })?; - } + gva_db.write(|mut db| { + db.blockchain_time.remove(U32BE(block.number().0)); + identities::revert_identities::<B>(&block, &mut db.gva_identities)?; + if let Some(divident_amount) = block.dividend() { + db.blocks_with_ud.remove(U32BE(block.number().0)); + revert_ud::<B>( + block.number(), + divident_amount, + &mut db.balances, + &mut db.gva_identities, + )?; + } + + let mut scripts_hash = HashMap::with_capacity(block.transactions().len() * 3); + for tx in block.transactions() { + let tx_hash = tx.get_hash(); + tx::revert_tx::<B>(block.number(), &mut db, &mut scripts_hash, &tx_hash)?.ok_or_else( + || { + KvError::DbCorrupted(format!( + "GVA: tx '{}' dont exist on txs history.", + tx_hash, + )) + }, + )?; + } + Ok(()) + })?; Ok(()) } @@ -202,7 +192,7 @@ fn revert_ud<B: Backend>( } fn apply_block_txs<B: Backend>( - gva_db: &GvaV1Db<B>, + gva_db: &mut GvaV1DbTxRw<B::Col>, current_blockstamp: Blockstamp, current_time: i64, txs: &[TransactionDocumentV10], @@ -213,10 +203,10 @@ fn apply_block_txs<B: Backend>( for tx in txs { let tx_hash = tx.get_hash(); // Write tx and update sources - tx::apply_tx( + tx::apply_tx::<B>( current_blockstamp, current_time, - &gva_db, + gva_db, &mut scripts_index, tx_hash, tx, @@ -224,19 +214,13 @@ fn apply_block_txs<B: Backend>( &mut txs_by_recipient_mem, )?; } - ( - gva_db.txs_by_issuer_write(), - gva_db.txs_by_recipient_write(), - ) - .write(|(mut txs_by_issuer, mut txs_by_recipient)| { - for (k, v) in txs_by_issuer_mem { - txs_by_issuer.upsert(k, v); - } - for (k, v) in txs_by_recipient_mem { - txs_by_recipient.upsert(k, v); - } - Ok(()) - })?; + + for (k, v) in txs_by_issuer_mem { + gva_db.txs_by_issuer.upsert(k, v); + } + for (k, v) in txs_by_recipient_mem { + gva_db.txs_by_recipient.upsert(k, v); + } Ok(()) } diff --git a/rust-libs/modules/gva/indexer/src/tx.rs b/rust-libs/modules/gva/indexer/src/tx.rs index ed3d23e91d24e88693b59e03557abfc0e6d45e88..740d174cac05266612aa13ab9871f8f180e1e911 100644 --- a/rust-libs/modules/gva/indexer/src/tx.rs +++ b/rust-libs/modules/gva/indexer/src/tx.rs @@ -31,241 +31,201 @@ fn get_script_hash(script: &WalletScriptV10, scripts_hash: &mut ScriptsHash) -> pub(crate) fn apply_tx<B: Backend>( current_blockstamp: Blockstamp, current_time: i64, - gva_db: &GvaV1Db<B>, + gva_db: &mut GvaV1DbTxRw<B::Col>, scripts_hash: &mut ScriptsHash, tx_hash: Hash, tx: &TransactionDocumentV10, txs_by_issuer_mem: &mut HashMap<WalletHashWithBnV1Db, BTreeSet<Hash>>, txs_by_recipient_mem: &mut HashMap<WalletHashWithBnV1Db, BTreeSet<Hash>>, ) -> KvResult<()> { - ( - gva_db.scripts_by_pubkey_write(), - gva_db.txs_write(), - gva_db.gva_utxos_write(), - gva_db.balances_write(), - ) - .write( - |(mut scripts_by_pubkey, mut txs, mut gva_utxos, mut balances)| { - let mut issuers_scripts_hashs = BTreeSet::new(); - for input in tx.get_inputs() { - let (account_script_hash, account_script) = match input.id { - SourceIdV10::Utxo(utxo_id) => { - // Get issuer script & written block - let db_tx_origin = gva_db - .txs() - .get(&HashKeyV2::from_ref(&utxo_id.tx_hash))? - .ok_or_else(|| { - KvError::DbCorrupted(format!( - "Not found origin tx of uxto {}", - utxo_id - )) - })?; - let utxo_script = db_tx_origin.tx.get_outputs()[utxo_id.output_index] - .conditions - .script - .clone(); - let utxo_script_hash = get_script_hash(&utxo_script, scripts_hash); - - // Remove consumed UTXOs - super::utxos::remove_utxo_v10::<B>( - &mut scripts_by_pubkey, - &mut gva_utxos, - utxo_id, - &utxo_script, - utxo_script_hash, - db_tx_origin.written_block.number.0, - )?; - - // Return utxo_script with hash - (utxo_script_hash, utxo_script) - } - SourceIdV10::Ud(UdSourceIdV10 { issuer, .. }) => { - let script = WalletScriptV10::single_sig(issuer); - (Hash::compute(script.to_string().as_bytes()), script) - } - }; - issuers_scripts_hashs.insert(account_script_hash); - // Insert on col `txs_by_issuer` - txs_by_issuer_mem - .entry(WalletHashWithBnV1Db::new( - account_script_hash, - current_blockstamp.number, - )) - .or_default() - .insert(tx_hash); - // Decrease account balance - decrease_account_balance::<B>(account_script, &mut balances, input.amount)?; - } - - for (output_index, output) in tx.get_outputs().iter().enumerate() { - let utxo_script_hash = get_script_hash(&output.conditions.script, scripts_hash); - // Insert created UTXOs - super::utxos::write_utxo_v10::<B>( - &mut scripts_by_pubkey, - &mut gva_utxos, - UtxoV10 { - id: UtxoIdV10 { - tx_hash, - output_index, - }, - amount: output.amount, - script: &output.conditions.script, - written_block: current_blockstamp.number, - }, - utxo_script_hash, - )?; - - // Insert on col `txs_by_recipient` - if !issuers_scripts_hashs.contains(&utxo_script_hash) { - txs_by_recipient_mem - .entry(WalletHashWithBnV1Db::new( - utxo_script_hash, - current_blockstamp.number, - )) - .or_default() - .insert(tx_hash); - } - - // Increase account balance - let balance = balances - .get(WalletConditionsV2::from_ref(&output.conditions.script))? - .unwrap_or_default(); - balances.upsert( - WalletConditionsV2(output.conditions.script.clone()), - SourceAmountValV2(balance.0 + output.amount), - ); - } + let mut issuers_scripts_hashs = BTreeSet::new(); + for input in tx.get_inputs() { + let (account_script_hash, account_script) = match input.id { + SourceIdV10::Utxo(utxo_id) => { + // Get issuer script & written block + let db_tx_origin = gva_db + .txs + .get(&HashKeyV2::from_ref(&utxo_id.tx_hash))? + .ok_or_else(|| { + KvError::DbCorrupted(format!("Not found origin tx of uxto {}", utxo_id)) + })?; + let utxo_script = db_tx_origin.tx.get_outputs()[utxo_id.output_index] + .conditions + .script + .clone(); + let utxo_script_hash = get_script_hash(&utxo_script, scripts_hash); + + // Remove consumed UTXOs + super::utxos::remove_utxo_v10::<B>( + &mut gva_db.scripts_by_pubkey, + &mut gva_db.gva_utxos, + utxo_id, + &utxo_script, + utxo_script_hash, + db_tx_origin.written_block.number.0, + )?; + + // Return utxo_script with hash + (utxo_script_hash, utxo_script) + } + SourceIdV10::Ud(UdSourceIdV10 { issuer, .. }) => { + let script = WalletScriptV10::single_sig(issuer); + (Hash::compute(script.to_string().as_bytes()), script) + } + }; + issuers_scripts_hashs.insert(account_script_hash); + // Insert on col `txs_by_issuer` + txs_by_issuer_mem + .entry(WalletHashWithBnV1Db::new( + account_script_hash, + current_blockstamp.number, + )) + .or_default() + .insert(tx_hash); + // Decrease account balance + decrease_account_balance::<B>(account_script, &mut gva_db.balances, input.amount)?; + } - // Insert tx itself - txs.upsert( - HashKeyV2(tx_hash), - GvaTxDbV1 { - tx: tx.clone(), - written_block: current_blockstamp, - written_time: current_time, - }, - ); - - Ok(()) + for (output_index, output) in tx.get_outputs().iter().enumerate() { + let utxo_script_hash = get_script_hash(&output.conditions.script, scripts_hash); + // Insert created UTXOs + super::utxos::write_utxo_v10::<B>( + &mut gva_db.scripts_by_pubkey, + &mut gva_db.gva_utxos, + UtxoV10 { + id: UtxoIdV10 { + tx_hash, + output_index, + }, + amount: output.amount, + script: &output.conditions.script, + written_block: current_blockstamp.number, }, + utxo_script_hash, )?; + // Insert on col `txs_by_recipient` + if !issuers_scripts_hashs.contains(&utxo_script_hash) { + txs_by_recipient_mem + .entry(WalletHashWithBnV1Db::new( + utxo_script_hash, + current_blockstamp.number, + )) + .or_default() + .insert(tx_hash); + } + + // Increase account balance + let balance = gva_db + .balances + .get(WalletConditionsV2::from_ref(&output.conditions.script))? + .unwrap_or_default(); + gva_db.balances.upsert( + WalletConditionsV2(output.conditions.script.clone()), + SourceAmountValV2(balance.0 + output.amount), + ); + } + + // Insert tx itself + gva_db.txs.upsert( + HashKeyV2(tx_hash), + GvaTxDbV1 { + tx: tx.clone(), + written_block: current_blockstamp, + written_time: current_time, + }, + ); + Ok(()) } pub(crate) fn revert_tx<B: Backend>( block_number: BlockNumber, - gva_db: &GvaV1Db<B>, + gva_db: &mut GvaV1DbTxRw<B::Col>, scripts_hash: &mut ScriptsHash, tx_hash: &Hash, ) -> KvResult<Option<TransactionDocumentV10>> { - if let Some(tx_db) = gva_db.txs().get(&HashKeyV2::from_ref(tx_hash))? { - ( - gva_db.scripts_by_pubkey_write(), - gva_db.txs_by_issuer_write(), - gva_db.txs_by_recipient_write(), - gva_db.txs_write(), - gva_db.gva_utxos_write(), - gva_db.balances_write(), - ) - .write( - |( - mut scripts_by_pubkey, - mut txs_by_issuer, - mut txs_by_recipient, - mut txs, - mut gva_utxos, - mut balances, - )| { - use dubp::documents::transaction::TransactionDocumentTrait as _; - for (output_index, output) in tx_db.tx.get_outputs().iter().enumerate() { - let script = &output.conditions.script; - let utxo_script_hash = get_script_hash(&script, scripts_hash); - - // Remove UTXOs created by this tx - super::utxos::remove_utxo_v10::<B>( - &mut scripts_by_pubkey, - &mut gva_utxos, - UtxoIdV10 { - tx_hash: *tx_hash, - output_index, - }, - script, - utxo_script_hash, - block_number.0, - )?; - - // Remove on col `txs_by_recipient` - txs_by_recipient - .remove(WalletHashWithBnV1Db::new(utxo_script_hash, block_number)); - - // Decrease account balance - decrease_account_balance::<B>( - script.clone(), - &mut balances, - output.amount, - )?; - } - // Recreate UTXOs consumed by this tx (and update balance) - for input in tx_db.tx.get_inputs() { - let (account_script_hash, account_script) = match input.id { - SourceIdV10::Utxo(utxo_id) => { - let db_tx_origin = gva_db - .txs() - .get(&HashKeyV2::from_ref(&utxo_id.tx_hash))? - .ok_or_else(|| { - KvError::DbCorrupted(format!( - "Not found origin tx of uxto {}", - utxo_id - )) - })?; - let utxo_script = db_tx_origin.tx.get_outputs() - [utxo_id.output_index] - .conditions - .script - .clone(); - let utxo_script_hash = get_script_hash(&utxo_script, scripts_hash); - super::utxos::write_utxo_v10::<B>( - &mut scripts_by_pubkey, - &mut gva_utxos, - UtxoV10 { - id: utxo_id, - amount: input.amount, - script: &utxo_script, - written_block: db_tx_origin.written_block.number, - }, - utxo_script_hash, - )?; - - // Return utxo_script - (utxo_script_hash, utxo_script) - } - SourceIdV10::Ud(UdSourceIdV10 { issuer, .. }) => { - let script = WalletScriptV10::single_sig(issuer); - (Hash::compute(script.to_string().as_bytes()), script) - } - }; - // Remove on col `txs_by_issuer` - txs_by_issuer - .remove(WalletHashWithBnV1Db::new(account_script_hash, block_number)); - // Increase account balance - let balance = balances - .get(WalletConditionsV2::from_ref(&account_script))? - .unwrap_or_default(); - - balances.upsert( - WalletConditionsV2(account_script), - SourceAmountValV2(balance.0 + input.amount), - ); - } - - // Remove tx itself - txs.remove(HashKeyV2(*tx_hash)); - - Ok(()) + if let Some(tx_db) = gva_db.txs.get(&HashKeyV2::from_ref(tx_hash))? { + use dubp::documents::transaction::TransactionDocumentTrait as _; + for (output_index, output) in tx_db.tx.get_outputs().iter().enumerate() { + let script = &output.conditions.script; + let utxo_script_hash = get_script_hash(&script, scripts_hash); + + // Remove UTXOs created by this tx + super::utxos::remove_utxo_v10::<B>( + &mut gva_db.scripts_by_pubkey, + &mut gva_db.gva_utxos, + UtxoIdV10 { + tx_hash: *tx_hash, + output_index, }, + script, + utxo_script_hash, + block_number.0, )?; + // Remove on col `txs_by_recipient` + gva_db + .txs_by_recipient + .remove(WalletHashWithBnV1Db::new(utxo_script_hash, block_number)); + + // Decrease account balance + decrease_account_balance::<B>(script.clone(), &mut gva_db.balances, output.amount)?; + } + // Recreate UTXOs consumed by this tx (and update balance) + for input in tx_db.tx.get_inputs() { + let (account_script_hash, account_script) = match input.id { + SourceIdV10::Utxo(utxo_id) => { + let db_tx_origin = gva_db + .txs + .get(&HashKeyV2::from_ref(&utxo_id.tx_hash))? + .ok_or_else(|| { + KvError::DbCorrupted(format!("Not found origin tx of uxto {}", utxo_id)) + })?; + let utxo_script = db_tx_origin.tx.get_outputs()[utxo_id.output_index] + .conditions + .script + .clone(); + let utxo_script_hash = get_script_hash(&utxo_script, scripts_hash); + super::utxos::write_utxo_v10::<B>( + &mut gva_db.scripts_by_pubkey, + &mut gva_db.gva_utxos, + UtxoV10 { + id: utxo_id, + amount: input.amount, + script: &utxo_script, + written_block: db_tx_origin.written_block.number, + }, + utxo_script_hash, + )?; + + // Return utxo_script + (utxo_script_hash, utxo_script) + } + SourceIdV10::Ud(UdSourceIdV10 { issuer, .. }) => { + let script = WalletScriptV10::single_sig(issuer); + (Hash::compute(script.to_string().as_bytes()), script) + } + }; + // Remove on col `txs_by_issuer` + gva_db + .txs_by_issuer + .remove(WalletHashWithBnV1Db::new(account_script_hash, block_number)); + // Increase account balance + let balance = gva_db + .balances + .get(WalletConditionsV2::from_ref(&account_script))? + .unwrap_or_default(); + + gva_db.balances.upsert( + WalletConditionsV2(account_script), + SourceAmountValV2(balance.0 + input.amount), + ); + } + + // Remove tx itself + gva_db.txs.remove(HashKeyV2(*tx_hash)); + Ok(Some(tx_db.tx)) } else { Ok(None) @@ -364,16 +324,18 @@ mod tests { let mut txs_by_issuer_mem = HashMap::new(); let mut txs_by_recipient_mem = HashMap::new(); - apply_tx( - current_blockstamp, - b0.median_time as i64, - &gva_db, - &mut scripts_hash, - tx1_hash, - &tx1, - &mut txs_by_issuer_mem, - &mut txs_by_recipient_mem, - )?; + (&gva_db).write(|mut db| { + apply_tx::<Mem>( + current_blockstamp, + b0.median_time as i64, + &mut db, + &mut scripts_hash, + tx1_hash, + &tx1, + &mut txs_by_issuer_mem, + &mut txs_by_recipient_mem, + ) + })?; assert_eq!(txs_by_issuer_mem.len(), 1); assert_eq!( @@ -424,16 +386,18 @@ mod tests { let mut txs_by_issuer_mem = HashMap::new(); let mut txs_by_recipient_mem = HashMap::new(); - apply_tx( - current_blockstamp, - b0.median_time as i64, - &gva_db, - &mut scripts_hash, - tx2_hash, - &tx2, - &mut txs_by_issuer_mem, - &mut txs_by_recipient_mem, - )?; + (&gva_db).write(|mut db| { + apply_tx::<Mem>( + current_blockstamp, + b0.median_time as i64, + &mut db, + &mut scripts_hash, + tx2_hash, + &tx2, + &mut txs_by_issuer_mem, + &mut txs_by_recipient_mem, + ) + })?; assert_eq!(txs_by_issuer_mem.len(), 1); assert_eq!( @@ -459,12 +423,14 @@ mod tests { Some(SourceAmountValV2(ud0_amount)) ); - revert_tx( - current_blockstamp.number, - &gva_db, - &mut scripts_hash, - &tx2_hash, - )?; + (&gva_db).write(|mut db| { + revert_tx::<Mem>( + current_blockstamp.number, + &mut db, + &mut scripts_hash, + &tx2_hash, + ) + })?; assert_eq!( gva_db @@ -479,12 +445,14 @@ mod tests { Some(SourceAmountValV2(o2_amount)) ); - revert_tx( - current_blockstamp.number, - &gva_db, - &mut scripts_hash, - &tx1_hash, - )?; + (&gva_db).write(|mut db| { + revert_tx::<Mem>( + current_blockstamp.number, + &mut db, + &mut scripts_hash, + &tx1_hash, + ) + })?; assert_eq!( gva_db diff --git a/rust-libs/tools/kv_typed/Cargo.toml b/rust-libs/tools/kv_typed/Cargo.toml index 86471ccf91a10a9596d8f9237ae31ea8391b3780..0761bbb5152e8a55c43bc0f55ccd800d0abcd107 100644 --- a/rust-libs/tools/kv_typed/Cargo.toml +++ b/rust-libs/tools/kv_typed/Cargo.toml @@ -23,7 +23,7 @@ paste = "1.0.2" rayon = { version = "1.3.1", optional = true } regex = { version = "1.3.9", optional = true } serde_json = { version = "1.0.53", optional = true } -sled = { version = "0.34.4", optional = true, features = ["compression"] } +sled = { version = "0.34.6", optional = true, features = ["compression"] } smallvec = { version = "1.4.0", features = ["serde", "write"] } thiserror = "1.0.20" uninit = "0.4.0" diff --git a/rust-libs/tools/kv_typed/src/db_schema.rs b/rust-libs/tools/kv_typed/src/db_schema.rs index 3f1d3f3168dbe96b44de8f05656c704ddc361d05..657d7797dcd12e1d075ed1a83e69c3e5a589181c 100644 --- a/rust-libs/tools/kv_typed/src/db_schema.rs +++ b/rust-libs/tools/kv_typed/src/db_schema.rs @@ -35,7 +35,7 @@ macro_rules! db_schema { } )* // Inner module used to hide internals types that must not be exposed on public api - pub use __inner::{[<$db_name Db>], [<$db_name DbRo>], [<$db_name DbWritable>], [<$db_name DbReadable>]}; + pub use __inner::{[<$db_name Db>], [<$db_name DbRo>], [<$db_name DbWritable>], [<$db_name DbReadable>], [<$db_name DbTxRw>]}; mod __inner { use super::*; use kv_typed::prelude::*;