cuprate_consensus/transactions/
free.rs1use monero_oxide::{
2 ringct::{bulletproofs::Bulletproof, RctType},
3 transaction::{Input, Transaction},
4};
5
6use cuprate_consensus_rules::{transactions::TransactionError, ConsensusError};
7use cuprate_types::{CachedVerificationState, TransactionVerificationData, TxVersion};
8
9pub fn new_tx_verification_data(
16 tx: Transaction,
17) -> Result<TransactionVerificationData, ConsensusError> {
18 let tx_hash = tx.hash();
19 let tx_blob = tx.serialize();
20
21 let tx_weight = tx_weight(&tx, &tx_blob);
22
23 let fee = tx_fee(&tx)?;
24
25 Ok(TransactionVerificationData {
26 tx_hash,
27 version: TxVersion::from_raw(tx.version())
28 .ok_or(TransactionError::TransactionVersionInvalid)?,
29 tx_blob,
30 tx_weight,
31 fee,
32 cached_verification_state: CachedVerificationState::NotVerified,
33 tx,
34 })
35}
36
37pub(crate) fn tx_weight(tx: &Transaction, tx_blob: &[u8]) -> usize {
41 match &tx {
44 Transaction::V1 { .. } | Transaction::V2 { proofs: None, .. } => tx_blob.len(),
45 Transaction::V2 {
46 proofs: Some(proofs),
47 ..
48 } => match proofs.rct_type() {
49 RctType::AggregateMlsagBorromean | RctType::MlsagBorromean => tx_blob.len(),
50 RctType::MlsagBulletproofs
51 | RctType::MlsagBulletproofsCompactAmount
52 | RctType::ClsagBulletproof => {
53 tx_blob.len() + Bulletproof::calculate_clawback(false, tx.prefix().outputs.len()).0
54 }
55 RctType::ClsagBulletproofPlus => {
56 tx_blob.len() + Bulletproof::calculate_clawback(true, tx.prefix().outputs.len()).0
57 }
58 },
59 }
60}
61
62pub(crate) fn tx_fee(tx: &Transaction) -> Result<u64, TransactionError> {
64 let mut fee = 0_u64;
65
66 match &tx {
67 Transaction::V1 { prefix, .. } => {
68 for input in &prefix.inputs {
69 if let Input::ToKey { amount, .. } = input {
70 fee = fee
71 .checked_add(amount.unwrap_or(0))
72 .ok_or(TransactionError::InputsOverflow)?;
73 }
74 }
75
76 for output in &prefix.outputs {
77 fee = fee
78 .checked_sub(output.amount.unwrap_or(0))
79 .ok_or(TransactionError::OutputsTooHigh)?;
80 }
81 }
82 Transaction::V2 { proofs, .. } => {
83 fee = proofs
84 .as_ref()
85 .ok_or(TransactionError::TransactionVersionInvalid)?
86 .base
87 .fee;
88 }
89 }
90
91 Ok(fee)
92}