cuprate_txpool/ops.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
//! Abstracted Monero tx-pool database operations.
//!
//! This module contains many free functions that use the
//! traits in [`cuprate_database`] to generically call Monero-related
//! tx-pool database operations.
//!
//! # `impl Table`
//! Functions in this module take [`Tables`](crate::tables::Tables) and
//! [`TablesMut`](crate::tables::TablesMut) directly - these are
//! _already opened_ database tables.
//!
//! As such, the responsibility of
//! transactions, tables, etc, are on the caller.
//!
//! Notably, this means that these functions are as lean
//! as possible, so calling them in a loop should be okay.
//!
//! # Atomicity
//! As transactions are handled by the _caller_ of these functions,
//! it is up to the caller to decide what happens if one them return
//! an error.
//!
//! To maintain atomicity, transactions should be [`abort`](cuprate_database::TxRw::abort)ed
//! if one of the functions failed.
//!
//! For example, if [`add_transaction`] is called and returns an [`Err`],
//! `abort`ing the transaction that opened the input `TableMut` would reverse all tables
//! mutated by [`add_transaction`] up until the error, leaving it in the state it was in before
//! [`add_transaction`] was called.
//!
//! # Example
//! Simple usage of `ops`.
//!
//! ```rust
//! use hex_literal::hex;
//!
//! use cuprate_test_utils::data::TX_V1_SIG2;
//! use cuprate_txpool::{
//! cuprate_database::{
//! ConcreteEnv,
//! Env, EnvInner,
//! DatabaseRo, DatabaseRw, TxRo, TxRw,
//! },
//! config::ConfigBuilder,
//! tables::{Tables, TablesMut, OpenTables},
//! ops::{add_transaction, get_transaction_verification_data},
//! };
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // Create a configuration for the database environment.
//! let tmp_dir = tempfile::tempdir()?;
//! let db_dir = tmp_dir.path().to_owned();
//! let config = ConfigBuilder::new()
//! .db_directory(db_dir.into())
//! .build();
//!
//! // Initialize the database environment.
//! let env = cuprate_txpool::open(config)?;
//!
//! // Open up a transaction + tables for writing.
//! let env_inner = env.env_inner();
//! let tx_rw = env_inner.tx_rw()?;
//! let mut tables = env_inner.open_tables_mut(&tx_rw)?;
//!
//! // Write a tx to the database.
//! let mut tx = TX_V1_SIG2.clone();
//! let tx_hash = tx.tx_hash;
//! add_transaction(&tx.try_into().unwrap(), true, &mut tables)?;
//!
//! // Commit the data written.
//! drop(tables);
//! TxRw::commit(tx_rw)?;
//!
//! // Read the data, assert it is correct.
//! let tx_rw = env_inner.tx_rw()?;
//! let mut tables = env_inner.open_tables_mut(&tx_rw)?;
//! let tx = get_transaction_verification_data(&tx_hash, &mut tables)?;
//!
//! assert_eq!(tx.tx_hash, tx_hash);
//! assert_eq!(tx.tx, TX_V1_SIG2.tx);
//! # Ok(()) }
//! ```
mod key_images;
mod tx_read;
mod tx_write;
pub use tx_read::{get_transaction_verification_data, in_stem_pool};
pub use tx_write::{add_transaction, remove_transaction};
/// An error that can occur on some tx-write ops.
#[derive(thiserror::Error, Debug)]
pub enum TxPoolWriteError {
/// The transaction could not be added as it double spends another tx in the pool.
///
/// The inner value is the hash of the transaction that was double spent.
#[error("Transaction doubles spent transaction already in the pool ({}).", hex::encode(.0))]
DoubleSpend(crate::types::TransactionHash),
/// A database error.
#[error("Database error: {0}")]
Database(#[from] cuprate_database::RuntimeError),
}