cuprate_txpool/
ops.rs

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