Skip to content

Commit

Permalink
misc changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Boog900 committed Aug 1, 2024
1 parent 4c31072 commit f48ea91
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 59 deletions.
54 changes: 4 additions & 50 deletions consensus/src/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ use std::{
};

use futures::FutureExt;
use monero_serai::ringct::bulletproofs::Bulletproof;
use monero_serai::{
ringct::RctType,
transaction::{Input, Timelock, Transaction},
};
use monero_serai::transaction::{Input, Timelock, Transaction};
use rayon::prelude::*;
use tower::{Service, ServiceExt};
use tracing::instrument;
Expand All @@ -38,6 +34,7 @@ use crate::{
};

pub mod contextual_data;
mod free;

/// A struct representing the type of validation that needs to be completed for this transaction.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
Expand Down Expand Up @@ -104,52 +101,9 @@ impl TransactionVerificationData {
let tx_hash = tx.hash();
let tx_blob = tx.serialize();

// the tx weight is only different from the blobs length for bp(+) txs.
let tx_weight = match &tx {
Transaction::V1 { .. } | Transaction::V2 { proofs: None, .. } => tx_blob.len(),
Transaction::V2 {
proofs: Some(proofs),
..
} => match proofs.rct_type() {
RctType::AggregateMlsagBorromean | RctType::MlsagBorromean => tx_blob.len(),
RctType::MlsagBulletproofs
| RctType::MlsagBulletproofsCompactAmount
| RctType::ClsagBulletproof => {
tx_blob.len()
+ Bulletproof::calculate_bp_clawback(false, tx.prefix().outputs.len()).0
}
RctType::ClsagBulletproofPlus => {
tx_blob.len()
+ Bulletproof::calculate_bp_clawback(true, tx.prefix().outputs.len()).0
}
},
};

let mut fee = 0_u64;
let tx_weight = free::tx_weight(&tx, &tx_blob);

match &tx {
Transaction::V1 { prefix, .. } => {
for input in &prefix.inputs {
if let Input::ToKey { amount, .. } = input {
fee = fee
.checked_add(amount.unwrap_or(0))
.ok_or(TransactionError::InputsOverflow)?;
}
}

for output in &prefix.outputs {
fee.checked_sub(output.amount.unwrap_or(0))
.ok_or(TransactionError::OutputsTooHigh)?;
}
}
Transaction::V2 { proofs, .. } => {
fee = proofs
.as_ref()
.ok_or(TransactionError::TransactionVersionInvalid)?
.base
.fee;
}
};
let fee = free::tx_fee(&tx)?;

Ok(TransactionVerificationData {
tx_hash,
Expand Down
64 changes: 64 additions & 0 deletions consensus/src/transactions/free.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use monero_serai::{
ringct::{bulletproofs::Bulletproof, RctType},
transaction::{Input, Transaction},
};

use cuprate_consensus_rules::transactions::TransactionError;

/// Calculates the weight of a [`Transaction`].
///
/// This is more efficient that [`Transaction::weight`] if you already have the transaction blob.
pub fn tx_weight(tx: &Transaction, tx_blob: &[u8]) -> usize {
// the tx weight is only different from the blobs length for bp(+) txs.

match &tx {
Transaction::V1 { .. } | Transaction::V2 { proofs: None, .. } => tx_blob.len(),
Transaction::V2 {
proofs: Some(proofs),
..
} => match proofs.rct_type() {
RctType::AggregateMlsagBorromean | RctType::MlsagBorromean => tx_blob.len(),
RctType::MlsagBulletproofs
| RctType::MlsagBulletproofsCompactAmount
| RctType::ClsagBulletproof => {
tx_blob.len()
+ Bulletproof::calculate_bp_clawback(false, tx.prefix().outputs.len()).0
}
RctType::ClsagBulletproofPlus => {
tx_blob.len()
+ Bulletproof::calculate_bp_clawback(true, tx.prefix().outputs.len()).0
}
},
}
}

/// Calculates the fee of the [`Transaction`].
pub fn tx_fee(tx: &Transaction) -> Result<u64, TransactionError> {
let mut fee = 0_u64;

match &tx {
Transaction::V1 { prefix, .. } => {
for input in &prefix.inputs {
if let Input::ToKey { amount, .. } = input {
fee = fee
.checked_add(amount.unwrap_or(0))
.ok_or(TransactionError::InputsOverflow)?;
}
}

for output in &prefix.outputs {
fee.checked_sub(output.amount.unwrap_or(0))
.ok_or(TransactionError::OutputsTooHigh)?;
}
}
Transaction::V2 { proofs, .. } => {
fee = proofs
.as_ref()
.ok_or(TransactionError::TransactionVersionInvalid)?
.base
.fee;
}
};

Ok(fee)
}
37 changes: 32 additions & 5 deletions test-utils/src/data/free.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
//---------------------------------------------------------------------------------------------------- Import
use std::sync::OnceLock;

use hex_literal::hex;
use monero_serai::{block::Block, transaction::Transaction};

use cuprate_helper::map::combine_low_high_bits_to_u128;
use cuprate_types::{VerifiedBlockInformation, VerifiedTransactionInformation};
use hex_literal::hex;
use monero_serai::transaction::Input;
use monero_serai::{block::Block, transaction::Transaction};

use crate::data::constants::{
BLOCK_43BD1F, BLOCK_5ECB7E, BLOCK_F91043, TX_2180A8, TX_3BC7FF, TX_84D48D, TX_9E3F73,
Expand Down Expand Up @@ -104,13 +104,41 @@ fn to_tx_verification_data(tx_blob: impl AsRef<[u8]>) -> VerifiedTransactionInfo
VerifiedTransactionInformation {
tx_weight: tx.weight(),
// TODO:
fee: 0,
fee: tx_fee(&tx),
tx_hash: tx.hash(),
tx_blob,
tx,
}
}

/// Calculates the fee of the [`Transaction`].
///
/// # Panics
/// This will panic if the inputs overflow or the transaction outputs too much.
///
pub fn tx_fee(tx: &Transaction) -> u64 {
let mut fee = 0_u64;

match &tx {
Transaction::V1 { prefix, .. } => {
for input in &prefix.inputs {
if let Input::ToKey { amount, .. } = input {
fee = fee.checked_add(amount.unwrap_or(0)).unwrap();
}
}

for output in &prefix.outputs {
fee.checked_sub(output.amount.unwrap_or(0)).unwrap();
}
}
Transaction::V2 { proofs, .. } => {
fee = proofs.as_ref().unwrap().base.fee;
}
};

fee
}

//---------------------------------------------------------------------------------------------------- Blocks
/// Generate a block accessor function with this signature:
/// `fn() -> &'static VerifiedBlockInformation`
Expand Down Expand Up @@ -256,7 +284,6 @@ macro_rules! transaction_verification_data_fn {
#[doc = concat!("assert_eq!(tx.tx_blob, ", stringify!($tx_blob), ");")]
#[doc = concat!("assert_eq!(tx.tx_weight, ", $weight, ");")]
#[doc = concat!("assert_eq!(tx.tx_hash, hex!(\"", $hash, "\"));")]
// #[doc = "assert_eq!(tx.fee, tx.tx.rct_signatures.base.fee);"]
/// ```
pub fn $fn_name() -> &'static VerifiedTransactionInformation {
static TX: OnceLock<VerifiedTransactionInformation> = OnceLock::new();
Expand Down
4 changes: 3 additions & 1 deletion test-utils/src/data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ pub use constants::{
};

mod free;
pub use free::{block_v16_tx0, block_v1_tx2, block_v9_tx3, tx_v1_sig0, tx_v1_sig2, tx_v2_rct3};
pub use free::{
block_v16_tx0, block_v1_tx2, block_v9_tx3, tx_fee, tx_v1_sig0, tx_v1_sig2, tx_v2_rct3,
};
5 changes: 3 additions & 2 deletions test-utils/src/rpc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use monero_simple_request_rpc::SimpleRequestRpc;

use cuprate_types::{VerifiedBlockInformation, VerifiedTransactionInformation};

use crate::data::tx_fee;

//---------------------------------------------------------------------------------------------------- Constants
/// The default URL used for Monero RPC connections.
pub const LOCALHOST_RPC_URL: &str = "http://127.0.0.1:18081";
Expand Down Expand Up @@ -172,8 +174,7 @@ impl HttpRpcClient {
tx_blob: tx.serialize(),
tx_weight: tx.weight(),
tx_hash,
// TODO: fix this.
fee: 0,
fee: tx_fee(&tx),
tx,
}
})
Expand Down
1 change: 0 additions & 1 deletion types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ cuprate-fixed-bytes = { path = "../net/fixed-bytes" }
bytes = { workspace = true }
curve25519-dalek = { workspace = true }
monero-serai = { workspace = true }

serde = { workspace = true, features = ["derive"], optional = true }
borsh = { workspace = true, optional = true }

Expand Down

0 comments on commit f48ea91

Please sign in to comment.