1//! Tx-pool key image ops.
2use monero_serai::transaction::Input;
34use cuprate_database::{DatabaseRw, DbResult};
56use crate::{ops::TxPoolWriteError, tables::SpentKeyImages, types::TransactionHash};
78/// Adds the transaction key images to the [`SpentKeyImages`] table.
9///
10/// This function will return an error if any of the key images are already spent.
11///
12/// # Panics
13/// This function will panic if any of the [`Input`]s are not [`Input::ToKey`]
14pub(super) fn add_tx_key_images(
15 inputs: &[Input],
16 tx_hash: &TransactionHash,
17 kis_table: &mut impl DatabaseRw<SpentKeyImages>,
18) -> Result<(), TxPoolWriteError> {
19for ki in inputs.iter().map(ki_from_input) {
20if let Ok(double_spend_tx_hash) = kis_table.get(&ki) {
21return Err(TxPoolWriteError::DoubleSpend(double_spend_tx_hash));
22 }
2324 kis_table.put(&ki, tx_hash)?;
25 }
2627Ok(())
28}
2930/// Removes key images from the [`SpentKeyImages`] table.
31///
32/// # Panics
33/// This function will panic if any of the [`Input`]s are not [`Input::ToKey`]
34pub(super) fn remove_tx_key_images(
35 inputs: &[Input],
36 kis_table: &mut impl DatabaseRw<SpentKeyImages>,
37) -> DbResult<()> {
38for ki in inputs.iter().map(ki_from_input) {
39 kis_table.delete(&ki)?;
40 }
4142Ok(())
43}
4445/// Maps an input to a key image.
46///
47/// # Panics
48/// This function will panic if the [`Input`] is not [`Input::ToKey`]
49fn ki_from_input(input: &Input) -> [u8; 32] {
50match input {
51 Input::ToKey { key_image, .. } => key_image.0,
52 Input::Gen(_) => panic!("miner tx cannot be added to the txpool"),
53 }
54}