Skip to content
Snippets Groups Projects
Commit 7ef824c7 authored by Éloïs's avatar Éloïs
Browse files

Merge branch 'ref/gva-indexer/unified-db-tx' into 'dev'

Ref/gva indexer/unified db tx

See merge request nodes/typescript/duniter!1359
parents cb58c066 73f6d7dc
No related branches found
No related tags found
1 merge request!1GVA: heads and peers
......@@ -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",
......
......@@ -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)?;
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() {
blocks_with_ud.upsert(U32BE(blockstamp.number.0), ());
db.blocks_with_ud.upsert(U32BE(blockstamp.number.0), ());
apply_ud::<B>(
blockstamp.number,
divident_amount,
&mut balances,
&mut gva_identities,
&mut db.balances,
&mut db.gva_identities,
)?;
}
Ok(())
},
)?;
apply_block_txs(
&gva_db,
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)?;
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() {
blocks_with_ud.remove(U32BE(block.number().0));
db.blocks_with_ud.remove(U32BE(block.number().0));
revert_ud::<B>(
block.number(),
divident_amount,
&mut balances,
&mut gva_identities,
&mut db.balances,
&mut db.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,))
})?;
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,20 +214,14 @@ 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);
gva_db.txs_by_issuer.upsert(k, v);
}
for (k, v) in txs_by_recipient_mem {
txs_by_recipient.upsert(k, v);
gva_db.txs_by_recipient.upsert(k, v);
}
Ok(())
})?;
Ok(())
}
#[cfg(test)]
......
......@@ -31,34 +31,23 @@ 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()
.txs
.get(&HashKeyV2::from_ref(&utxo_id.tx_hash))?
.ok_or_else(|| {
KvError::DbCorrupted(format!(
"Not found origin tx of uxto {}",
utxo_id
))
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
......@@ -68,8 +57,8 @@ pub(crate) fn apply_tx<B: Backend>(
// Remove consumed UTXOs
super::utxos::remove_utxo_v10::<B>(
&mut scripts_by_pubkey,
&mut gva_utxos,
&mut gva_db.scripts_by_pubkey,
&mut gva_db.gva_utxos,
utxo_id,
&utxo_script,
utxo_script_hash,
......@@ -94,15 +83,15 @@ pub(crate) fn apply_tx<B: Backend>(
.or_default()
.insert(tx_hash);
// Decrease account balance
decrease_account_balance::<B>(account_script, &mut balances, input.amount)?;
decrease_account_balance::<B>(account_script, &mut gva_db.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,
&mut gva_db.scripts_by_pubkey,
&mut gva_db.gva_utxos,
UtxoV10 {
id: UtxoIdV10 {
tx_hash,
......@@ -127,17 +116,18 @@ pub(crate) fn apply_tx<B: Backend>(
}
// Increase account balance
let balance = balances
let balance = gva_db
.balances
.get(WalletConditionsV2::from_ref(&output.conditions.script))?
.unwrap_or_default();
balances.upsert(
gva_db.balances.upsert(
WalletConditionsV2(output.conditions.script.clone()),
SourceAmountValV2(balance.0 + output.amount),
);
}
// Insert tx itself
txs.upsert(
gva_db.txs.upsert(
HashKeyV2(tx_hash),
GvaTxDbV1 {
tx: tx.clone(),
......@@ -146,37 +136,16 @@ pub(crate) fn apply_tx<B: Backend>(
},
);
Ok(())
},
)?;
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,
)| {
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;
......@@ -184,8 +153,8 @@ pub(crate) fn revert_tx<B: Backend>(
// Remove UTXOs created by this tx
super::utxos::remove_utxo_v10::<B>(
&mut scripts_by_pubkey,
&mut gva_utxos,
&mut gva_db.scripts_by_pubkey,
&mut gva_db.gva_utxos,
UtxoIdV10 {
tx_hash: *tx_hash,
output_index,
......@@ -196,38 +165,31 @@ pub(crate) fn revert_tx<B: Backend>(
)?;
// Remove on col `txs_by_recipient`
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 balances,
output.amount,
)?;
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()
.txs
.get(&HashKeyV2::from_ref(&utxo_id.tx_hash))?
.ok_or_else(|| {
KvError::DbCorrupted(format!(
"Not found origin tx of uxto {}",
utxo_id
))
KvError::DbCorrupted(format!("Not found origin tx of uxto {}", utxo_id))
})?;
let utxo_script = db_tx_origin.tx.get_outputs()
[utxo_id.output_index]
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,
&mut gva_db.scripts_by_pubkey,
&mut gva_db.gva_utxos,
UtxoV10 {
id: utxo_id,
amount: input.amount,
......@@ -246,25 +208,23 @@ pub(crate) fn revert_tx<B: Backend>(
}
};
// Remove on col `txs_by_issuer`
txs_by_issuer
gva_db
.txs_by_issuer
.remove(WalletHashWithBnV1Db::new(account_script_hash, block_number));
// Increase account balance
let balance = balances
let balance = gva_db
.balances
.get(WalletConditionsV2::from_ref(&account_script))?
.unwrap_or_default();
balances.upsert(
gva_db.balances.upsert(
WalletConditionsV2(account_script),
SourceAmountValV2(balance.0 + input.amount),
);
}
// Remove tx itself
txs.remove(HashKeyV2(*tx_hash));
Ok(())
},
)?;
gva_db.txs.remove(HashKeyV2(*tx_hash));
Ok(Some(tx_db.tx))
} else {
......@@ -364,16 +324,18 @@ mod tests {
let mut txs_by_issuer_mem = HashMap::new();
let mut txs_by_recipient_mem = HashMap::new();
apply_tx(
(&gva_db).write(|mut db| {
apply_tx::<Mem>(
current_blockstamp,
b0.median_time as i64,
&gva_db,
&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(
(&gva_db).write(|mut db| {
apply_tx::<Mem>(
current_blockstamp,
b0.median_time as i64,
&gva_db,
&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(
(&gva_db).write(|mut db| {
revert_tx::<Mem>(
current_blockstamp.number,
&gva_db,
&mut db,
&mut scripts_hash,
&tx2_hash,
)?;
)
})?;
assert_eq!(
gva_db
......@@ -479,12 +445,14 @@ mod tests {
Some(SourceAmountValV2(o2_amount))
);
revert_tx(
(&gva_db).write(|mut db| {
revert_tx::<Mem>(
current_blockstamp.number,
&gva_db,
&mut db,
&mut scripts_hash,
&tx1_hash,
)?;
)
})?;
assert_eq!(
gva_db
......
......@@ -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"
......
......@@ -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::*;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment