cuprate_blockchain/ops/alt_block/
tx.rs

1use bytemuck::TransparentWrapper;
2use monero_serai::transaction::Transaction;
3
4use cuprate_database::{DatabaseRo, DatabaseRw, DbResult, RuntimeError, StorableVec};
5use cuprate_types::VerifiedTransactionInformation;
6
7use crate::{
8    ops::macros::{doc_add_alt_block_inner_invariant, doc_error},
9    tables::{Tables, TablesMut},
10    types::{AltTransactionInfo, TxHash},
11};
12
13/// Adds a [`VerifiedTransactionInformation`] from an alt-block
14/// if it is not already in the DB.
15///
16/// If the transaction is in the main-chain this function will still fill in the
17/// [`AltTransactionInfos`](crate::tables::AltTransactionInfos) table, as that
18/// table holds data which we don't keep around for main-chain txs.
19///
20#[doc = doc_add_alt_block_inner_invariant!()]
21#[doc = doc_error!()]
22pub fn add_alt_transaction_blob(
23    tx: &VerifiedTransactionInformation,
24    tables: &mut impl TablesMut,
25) -> DbResult<()> {
26    tables.alt_transaction_infos_mut().put(
27        &tx.tx_hash,
28        &AltTransactionInfo {
29            tx_weight: tx.tx_weight,
30            fee: tx.fee,
31            tx_hash: tx.tx_hash,
32        },
33    )?;
34
35    if tables.tx_ids().get(&tx.tx_hash).is_ok()
36        || tables.alt_transaction_blobs().get(&tx.tx_hash).is_ok()
37    {
38        return Ok(());
39    }
40
41    tables
42        .alt_transaction_blobs_mut()
43        .put(&tx.tx_hash, StorableVec::wrap_ref(&tx.tx_blob))?;
44
45    Ok(())
46}
47
48/// Retrieve a [`VerifiedTransactionInformation`] from the database.
49///
50#[doc = doc_error!()]
51pub fn get_alt_transaction(
52    tx_hash: &TxHash,
53    tables: &impl Tables,
54) -> DbResult<VerifiedTransactionInformation> {
55    let tx_info = tables.alt_transaction_infos().get(tx_hash)?;
56
57    let tx_blob = match tables.alt_transaction_blobs().get(tx_hash) {
58        Ok(blob) => blob.0,
59        Err(RuntimeError::KeyNotFound) => {
60            let tx_id = tables.tx_ids().get(tx_hash)?;
61
62            let blob = tables.tx_blobs().get(&tx_id)?;
63
64            blob.0
65        }
66        Err(e) => return Err(e),
67    };
68
69    Ok(VerifiedTransactionInformation {
70        tx: Transaction::read(&mut tx_blob.as_slice()).unwrap(),
71        tx_blob,
72        tx_weight: tx_info.tx_weight,
73        fee: tx_info.fee,
74        tx_hash: tx_info.tx_hash,
75    })
76}