cuprate_consensus/transactions/
free.rs1use monero_serai::{
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()
54 + Bulletproof::calculate_bp_clawback(false, tx.prefix().outputs.len()).0
55 }
56 RctType::ClsagBulletproofPlus => {
57 tx_blob.len()
58 + Bulletproof::calculate_bp_clawback(true, tx.prefix().outputs.len()).0
59 }
60 },
61 }
62}
63
64pub(crate) fn tx_fee(tx: &Transaction) -> Result<u64, TransactionError> {
66 let mut fee = 0_u64;
67
68 match &tx {
69 Transaction::V1 { prefix, .. } => {
70 for input in &prefix.inputs {
71 if let Input::ToKey { amount, .. } = input {
72 fee = fee
73 .checked_add(amount.unwrap_or(0))
74 .ok_or(TransactionError::InputsOverflow)?;
75 }
76 }
77
78 for output in &prefix.outputs {
79 fee = fee
80 .checked_sub(output.amount.unwrap_or(0))
81 .ok_or(TransactionError::OutputsTooHigh)?;
82 }
83 }
84 Transaction::V2 { proofs, .. } => {
85 fee = proofs
86 .as_ref()
87 .ok_or(TransactionError::TransactionVersionInvalid)?
88 .base
89 .fee;
90 }
91 };
92
93 Ok(fee)
94}