kaspa_mining/mempool/model/frontier/
feerate_key.rs1use crate::mempool::model::{frontier::selectors::ALPHA, tx::MempoolTransaction};
2use kaspa_consensus_core::mass::{ContextualMasses, Mass, MassCofactors};
3use kaspa_consensus_core::subnets::SubnetworkId;
4use kaspa_consensus_core::tx::Transaction;
5use std::sync::Arc;
6
7#[derive(Clone, Debug)]
8pub struct FeerateTransactionKey {
9 pub fee: u64,
10 pub mass: u64,
11 weight: f64,
12 pub tx: Arc<Transaction>,
13}
14
15impl Eq for FeerateTransactionKey {}
16
17impl PartialEq for FeerateTransactionKey {
18 fn eq(&self, other: &Self) -> bool {
19 self.tx.id() == other.tx.id()
20 }
21}
22
23impl FeerateTransactionKey {
24 pub fn new(fee: u64, mass: u64, tx: Arc<Transaction>) -> Self {
25 Self { fee, mass, weight: (fee as f64 / mass as f64).powi(ALPHA), tx }
32 }
33
34 pub fn feerate(&self) -> f64 {
35 self.fee as f64 / self.mass as f64
36 }
37
38 pub fn weight(&self) -> f64 {
39 self.weight
40 }
41
42 pub fn lane(&self) -> SubnetworkId {
43 self.tx.subnetwork_id
44 }
45}
46
47impl std::hash::Hash for FeerateTransactionKey {
48 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
49 self.tx.id().hash(state);
51 }
52}
53
54impl PartialOrd for FeerateTransactionKey {
55 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
56 Some(self.cmp(other))
57 }
58}
59
60impl Ord for FeerateTransactionKey {
61 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
62 match self.weight().total_cmp(&other.weight()) {
66 core::cmp::Ordering::Equal => {}
67 ord => return ord,
68 }
69
70 match self.fee.cmp(&other.fee) {
72 core::cmp::Ordering::Equal => {}
73 ord => return ord,
74 }
75
76 self.tx.id().cmp(&other.tx.id())
84 }
85}
86
87impl FeerateTransactionKey {
88 pub(crate) fn from_tx(tx: &MempoolTransaction, cofactors: &MassCofactors) -> Self {
89 let mass = Mass::new(
94 tx.mtx.calculated_non_contextual_masses.expect("masses are expected to be calculated"),
95 ContextualMasses::new(tx.mtx.tx.storage_mass()),
96 )
97 .normalized_max(cofactors);
98 let fee = tx.mtx.calculated_fee.expect("fee is expected to be populated");
99 Self::new(fee, mass, tx.mtx.tx.clone())
100 }
101}
102
103#[cfg(test)]
104pub(crate) mod tests {
105 use super::*;
106 use kaspa_consensus_core::{
107 subnets::SUBNETWORK_ID_NATIVE,
108 tx::{Transaction, TransactionInput, TransactionOutpoint},
109 };
110 use kaspa_hashes::{HasherBase, TransactionID};
111 use std::sync::Arc;
112
113 fn generate_unique_tx(i: u64) -> Arc<Transaction> {
114 let mut hasher = TransactionID::new();
115 let prev = hasher.update(i.to_le_bytes()).clone().finalize();
116 let input = TransactionInput::new(TransactionOutpoint::new(prev, 0), vec![], 0, 0);
117 Arc::new(Transaction::new(0, vec![input], vec![], 0, SUBNETWORK_ID_NATIVE, 0, vec![]))
118 }
119
120 pub(crate) fn build_feerate_key(fee: u64, mass: u64, id: u64) -> FeerateTransactionKey {
122 FeerateTransactionKey::new(fee, mass, generate_unique_tx(id))
123 }
124}