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

[ref] gva:indexer: apply & revert a block in one unified db tx

parent ecf43d46
Branches
No related tags found
1 merge request!1359Ref/gva indexer/unified db tx
......@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment