cuprate_txpool/ops/
tx_write.rs

1//! Transaction writing ops.
2//!
3//! This module handles writing full transaction data, like removing or adding a transaction.
4use bytemuck::TransparentWrapper;
5use monero_serai::transaction::{NotPruned, Transaction};
6
7use cuprate_database::{DatabaseRw, DbResult, StorableVec};
8use cuprate_helper::time::current_unix_timestamp;
9use cuprate_types::TransactionVerificationData;
10
11use crate::{
12    free::transaction_blob_hash,
13    ops::{
14        key_images::{add_tx_key_images, remove_tx_key_images},
15        TxPoolWriteError,
16    },
17    tables::TablesMut,
18    types::{TransactionHash, TransactionInfo, TxStateFlags},
19};
20
21/// Adds a transaction to the tx-pool.
22///
23/// This function fills in all tables necessary to add the transaction to the pool.
24///
25/// # Panics
26/// This function will panic if the transactions inputs are not all of type [`Input::ToKey`](monero_serai::transaction::Input::ToKey).
27pub fn add_transaction(
28    tx: &TransactionVerificationData,
29    state_stem: bool,
30    tables: &mut impl TablesMut,
31) -> Result<(), TxPoolWriteError> {
32    // Add the tx blob to table 0.
33    tables
34        .transaction_blobs_mut()
35        .put(&tx.tx_hash, StorableVec::wrap_ref(&tx.tx_blob))?;
36
37    let mut flags = TxStateFlags::empty();
38    flags.set(TxStateFlags::STATE_STEM, state_stem);
39
40    // Add the tx info to table 1.
41    tables.transaction_infos_mut().put(
42        &tx.tx_hash,
43        &TransactionInfo {
44            fee: tx.fee,
45            weight: tx.tx_weight,
46            received_at: current_unix_timestamp(),
47            flags,
48            _padding: [0; 7],
49        },
50    )?;
51
52    // Add the cached verification state to table 2.
53    let cached_verification_state = tx.cached_verification_state.into();
54    tables
55        .cached_verification_state_mut()
56        .put(&tx.tx_hash, &cached_verification_state)?;
57
58    // Add the tx key images to table 3.
59    let kis_table = tables.spent_key_images_mut();
60    add_tx_key_images(&tx.tx.prefix().inputs, &tx.tx_hash, kis_table)?;
61
62    // Add the blob hash to table 4.
63    let blob_hash = transaction_blob_hash(&tx.tx_blob);
64    tables
65        .known_blob_hashes_mut()
66        .put(&blob_hash, &tx.tx_hash)?;
67
68    Ok(())
69}
70
71/// Removes a transaction from the transaction pool.
72pub fn remove_transaction(tx_hash: &TransactionHash, tables: &mut impl TablesMut) -> DbResult<()> {
73    // Remove the tx blob from table 0.
74    let tx_blob = tables.transaction_blobs_mut().take(tx_hash)?.0;
75
76    // Remove the tx info from table 1.
77    tables.transaction_infos_mut().delete(tx_hash)?;
78
79    // Remove the cached verification state from table 2.
80    tables.cached_verification_state_mut().delete(tx_hash)?;
81
82    // Remove the tx key images from table 3.
83    let tx = Transaction::<NotPruned>::read(&mut tx_blob.as_slice())
84        .expect("Tx in the tx-pool must be parseable");
85    let kis_table = tables.spent_key_images_mut();
86    remove_tx_key_images(&tx.prefix().inputs, kis_table)?;
87
88    // Remove the blob hash from table 4.
89    let blob_hash = transaction_blob_hash(&tx_blob);
90    tables.known_blob_hashes_mut().delete(&blob_hash)?;
91
92    Ok(())
93}