cuprate_helper/
tx.rs

1//! Utils for working with [`Transaction`]
2
3use monero_serai::transaction::{Input, Transaction};
4
5/// Calculates the fee of the [`Transaction`].
6///
7/// # Panics
8/// This will panic if the inputs overflow or the transaction outputs too much, so should only
9/// be used on known to be valid txs.
10pub fn tx_fee(tx: &Transaction) -> u64 {
11    let mut fee = 0_u64;
12
13    match &tx {
14        Transaction::V1 { prefix, .. } => {
15            for input in &prefix.inputs {
16                match input {
17                    Input::Gen(_) => return 0,
18                    Input::ToKey { amount, .. } => {
19                        fee = fee.checked_add(amount.unwrap_or(0)).unwrap();
20                    }
21                }
22            }
23
24            for output in &prefix.outputs {
25                fee = fee.checked_sub(output.amount.unwrap_or(0)).unwrap();
26            }
27        }
28        Transaction::V2 { proofs, .. } => {
29            fee = proofs.as_ref().unwrap().base.fee;
30        }
31    };
32
33    fee
34}
35
36#[cfg(test)]
37mod test {
38    use curve25519_dalek::edwards::CompressedEdwardsY;
39    use monero_serai::transaction::{NotPruned, Output, Timelock, TransactionPrefix};
40
41    use super::*;
42
43    #[test]
44    #[should_panic(expected = "called `Option::unwrap()` on a `None` value")]
45    fn tx_fee_panic() {
46        let input = Input::ToKey {
47            amount: Some(u64::MAX),
48            key_offsets: vec![],
49            key_image: CompressedEdwardsY::default(),
50        };
51
52        let output = Output {
53            amount: Some(u64::MAX),
54            key: CompressedEdwardsY::default(),
55            view_tag: None,
56        };
57
58        let tx = Transaction::<NotPruned>::V1 {
59            prefix: TransactionPrefix {
60                additional_timelock: Timelock::None,
61                inputs: vec![input; 2],
62                outputs: vec![output],
63                extra: vec![],
64            },
65            signatures: vec![],
66        };
67
68        tx_fee(&tx);
69    }
70}