use crate::{block_template::selector::ALPHA, mempool::model::tx::MempoolTransaction};
use kaspa_consensus_core::tx::Transaction;
use std::sync::Arc;
#[derive(Clone, Debug)]
pub struct FeerateTransactionKey {
pub fee: u64,
pub mass: u64,
weight: f64,
pub tx: Arc<Transaction>,
}
impl Eq for FeerateTransactionKey {}
impl PartialEq for FeerateTransactionKey {
fn eq(&self, other: &Self) -> bool {
self.tx.id() == other.tx.id()
}
}
impl FeerateTransactionKey {
pub fn new(fee: u64, mass: u64, tx: Arc<Transaction>) -> Self {
Self { fee, mass, weight: (fee as f64 / mass as f64).powi(ALPHA), tx }
}
pub fn feerate(&self) -> f64 {
self.fee as f64 / self.mass as f64
}
pub fn weight(&self) -> f64 {
self.weight
}
}
impl std::hash::Hash for FeerateTransactionKey {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.tx.id().hash(state);
}
}
impl PartialOrd for FeerateTransactionKey {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for FeerateTransactionKey {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match self.weight().total_cmp(&other.weight()) {
core::cmp::Ordering::Equal => {}
ord => return ord,
}
match self.fee.cmp(&other.fee) {
core::cmp::Ordering::Equal => {}
ord => return ord,
}
self.tx.id().cmp(&other.tx.id())
}
}
impl From<&MempoolTransaction> for FeerateTransactionKey {
fn from(tx: &MempoolTransaction) -> Self {
let mass = tx.mtx.tx.mass();
let fee = tx.mtx.calculated_fee.expect("fee is expected to be populated");
assert_ne!(mass, 0, "mass field is expected to be set when inserting to the mempool");
Self::new(fee, mass, tx.mtx.tx.clone())
}
}
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use kaspa_consensus_core::{
subnets::SUBNETWORK_ID_NATIVE,
tx::{Transaction, TransactionInput, TransactionOutpoint},
};
use kaspa_hashes::{HasherBase, TransactionID};
use std::sync::Arc;
fn generate_unique_tx(i: u64) -> Arc<Transaction> {
let mut hasher = TransactionID::new();
let prev = hasher.update(i.to_le_bytes()).clone().finalize();
let input = TransactionInput::new(TransactionOutpoint::new(prev, 0), vec![], 0, 0);
Arc::new(Transaction::new(0, vec![input], vec![], 0, SUBNETWORK_ID_NATIVE, 0, vec![]))
}
pub(crate) fn build_feerate_key(fee: u64, mass: u64, id: u64) -> FeerateTransactionKey {
FeerateTransactionKey::new(fee, mass, generate_unique_tx(id))
}
}