return sigop-adjusted effective fee rates

This commit is contained in:
Mononaut 2023-07-03 12:01:06 -04:00
parent 078bc1d914
commit 897c667f17
No known key found for this signature in database
GPG key ID: A3F058E41374C04E
2 changed files with 34 additions and 20 deletions

View file

@ -15,6 +15,9 @@ pub struct AuditTransaction {
order: u32, order: u32,
pub fee: u64, pub fee: u64,
pub weight: u32, pub weight: u32,
// exact sigop-adjusted weight
pub sigop_adjusted_weight: u32,
// sigop-adjusted vsize rounded up the the next integer
pub sigop_adjusted_vsize: u32, pub sigop_adjusted_vsize: u32,
pub sigops: u32, pub sigops: u32,
adjusted_fee_per_vsize: f64, adjusted_fee_per_vsize: f64,
@ -25,7 +28,7 @@ pub struct AuditTransaction {
pub ancestors: HashSet<u32, U32HasherState>, pub ancestors: HashSet<u32, U32HasherState>,
pub children: HashSet<u32, U32HasherState>, pub children: HashSet<u32, U32HasherState>,
ancestor_fee: u64, ancestor_fee: u64,
ancestor_weight: u32, ancestor_sigop_adjusted_weight: u32,
ancestor_sigop_adjusted_vsize: u32, ancestor_sigop_adjusted_vsize: u32,
ancestor_sigops: u32, ancestor_sigops: u32,
// Safety: Must be private to prevent NaN breaking Ord impl. // Safety: Must be private to prevent NaN breaking Ord impl.
@ -85,36 +88,44 @@ impl Ord for AuditTransaction {
} }
#[inline] #[inline]
fn calc_fee_rate(fee: f64, vsize: u32) -> f64 { fn calc_fee_rate(fee: f64, vsize: f64) -> f64 {
fee / (if vsize == 0 { 1.0 } else { f64::from(vsize) }) fee / (if vsize == 0.0 { 1.0 } else { vsize })
} }
impl AuditTransaction { impl AuditTransaction {
pub fn from_thread_transaction(tx: &ThreadTransaction) -> Self { pub fn from_thread_transaction(tx: &ThreadTransaction) -> Self {
// rounded up to the nearest integer // rounded up to the nearest integer
let is_adjusted = tx.weight < (tx.sigops * 20);
let sigop_adjusted_vsize = ((tx.weight + 3) / 4).max(tx.sigops * 5); let sigop_adjusted_vsize = ((tx.weight + 3) / 4).max(tx.sigops * 5);
let sigop_adjusted_weight = tx.weight.max(tx.sigops * 20);
let effective_fee_per_vsize = if is_adjusted {
calc_fee_rate(tx.fee, f64::from(sigop_adjusted_weight) / 4.0)
} else {
tx.effective_fee_per_vsize
};
Self { Self {
uid: tx.uid, uid: tx.uid,
order: tx.order, order: tx.order,
fee: tx.fee as u64, fee: tx.fee as u64,
weight: tx.weight, weight: tx.weight,
sigop_adjusted_weight,
sigop_adjusted_vsize, sigop_adjusted_vsize,
sigops: tx.sigops, sigops: tx.sigops,
adjusted_fee_per_vsize: calc_fee_rate(tx.fee, sigop_adjusted_vsize), adjusted_fee_per_vsize: calc_fee_rate(tx.fee, f64::from(sigop_adjusted_vsize)),
effective_fee_per_vsize: tx.effective_fee_per_vsize, effective_fee_per_vsize,
dependency_rate: f64::INFINITY, dependency_rate: f64::INFINITY,
inputs: tx.inputs.clone(), inputs: tx.inputs.clone(),
relatives_set_flag: false, relatives_set_flag: false,
ancestors: u32hashset_new(), ancestors: u32hashset_new(),
children: u32hashset_new(), children: u32hashset_new(),
ancestor_fee: tx.fee as u64, ancestor_fee: tx.fee as u64,
ancestor_weight: tx.weight, ancestor_sigop_adjusted_weight: sigop_adjusted_weight,
ancestor_sigop_adjusted_vsize: sigop_adjusted_vsize, ancestor_sigop_adjusted_vsize: sigop_adjusted_vsize,
ancestor_sigops: tx.sigops, ancestor_sigops: tx.sigops,
score: 0.0, score: 0.0,
used: false, used: false,
modified: false, modified: false,
dirty: false, dirty: effective_fee_per_vsize != tx.effective_fee_per_vsize,
} }
} }
@ -144,8 +155,10 @@ impl AuditTransaction {
// Even if it could, as it approaches 0, the value inside the min() call // Even if it could, as it approaches 0, the value inside the min() call
// grows, so if we think of 0 as "grew infinitely" then dependency_rate would be // grows, so if we think of 0 as "grew infinitely" then dependency_rate would be
// the smaller of the two. If either side is NaN, the other side is returned. // the smaller of the two. If either side is NaN, the other side is returned.
self.dependency_rate self.dependency_rate.min(calc_fee_rate(
.min(self.ancestor_fee as f64 / (f64::from(self.ancestor_weight) / 4.0)) self.ancestor_fee as f64,
f64::from(self.ancestor_sigop_adjusted_weight) / 4.0,
))
} }
pub fn set_dirty_if_different(&mut self, cluster_rate: f64) { pub fn set_dirty_if_different(&mut self, cluster_rate: f64) {
@ -160,7 +173,7 @@ impl AuditTransaction {
fn calc_new_score(&mut self) { fn calc_new_score(&mut self) {
self.score = self.adjusted_fee_per_vsize.min(calc_fee_rate( self.score = self.adjusted_fee_per_vsize.min(calc_fee_rate(
self.ancestor_fee as f64, self.ancestor_fee as f64,
self.ancestor_sigop_adjusted_vsize, f64::from(self.ancestor_sigop_adjusted_vsize),
)); ));
} }
@ -169,13 +182,14 @@ impl AuditTransaction {
&mut self, &mut self,
ancestors: HashSet<u32, U32HasherState>, ancestors: HashSet<u32, U32HasherState>,
total_fee: u64, total_fee: u64,
total_weight: u32, total_sigop_adjusted_weight: u32,
total_sigop_adjusted_vsize: u32, total_sigop_adjusted_vsize: u32,
total_sigops: u32, total_sigops: u32,
) { ) {
self.ancestors = ancestors; self.ancestors = ancestors;
self.ancestor_fee = self.fee + total_fee; self.ancestor_fee = self.fee + total_fee;
self.ancestor_weight = self.weight + total_weight; self.ancestor_sigop_adjusted_weight =
self.sigop_adjusted_weight + total_sigop_adjusted_weight;
self.ancestor_sigop_adjusted_vsize = self.sigop_adjusted_vsize + total_sigop_adjusted_vsize; self.ancestor_sigop_adjusted_vsize = self.sigop_adjusted_vsize + total_sigop_adjusted_vsize;
self.ancestor_sigops = self.sigops + total_sigops; self.ancestor_sigops = self.sigops + total_sigops;
self.calc_new_score(); self.calc_new_score();
@ -187,7 +201,7 @@ impl AuditTransaction {
&mut self, &mut self,
root_txid: u32, root_txid: u32,
root_fee: u64, root_fee: u64,
root_weight: u32, root_sigop_adjusted_weight: u32,
root_sigop_adjusted_vsize: u32, root_sigop_adjusted_vsize: u32,
root_sigops: u32, root_sigops: u32,
cluster_rate: f64, cluster_rate: f64,
@ -196,7 +210,7 @@ impl AuditTransaction {
self.dependency_rate = self.dependency_rate.min(cluster_rate); self.dependency_rate = self.dependency_rate.min(cluster_rate);
if self.ancestors.remove(&root_txid) { if self.ancestors.remove(&root_txid) {
self.ancestor_fee -= root_fee; self.ancestor_fee -= root_fee;
self.ancestor_weight -= root_weight; self.ancestor_sigop_adjusted_weight -= root_sigop_adjusted_weight;
self.ancestor_sigop_adjusted_vsize -= root_sigop_adjusted_vsize; self.ancestor_sigop_adjusted_vsize -= root_sigop_adjusted_vsize;
self.ancestor_sigops -= root_sigops; self.ancestor_sigops -= root_sigops;
self.calc_new_score(); self.calc_new_score();

View file

@ -312,7 +312,7 @@ fn set_relatives(txid: u32, audit_pool: &mut AuditPool) {
} }
let mut total_fee: u64 = 0; let mut total_fee: u64 = 0;
let mut total_weight: u32 = 0; let mut total_sigop_adjusted_weight: u32 = 0;
let mut total_sigop_adjusted_vsize: u32 = 0; let mut total_sigop_adjusted_vsize: u32 = 0;
let mut total_sigops: u32 = 0; let mut total_sigops: u32 = 0;
@ -321,7 +321,7 @@ fn set_relatives(txid: u32, audit_pool: &mut AuditPool) {
.get(ancestor_id) .get(ancestor_id)
.expect("audit_pool contains all ancestors"); .expect("audit_pool contains all ancestors");
total_fee += ancestor.fee; total_fee += ancestor.fee;
total_weight += ancestor.weight; total_sigop_adjusted_weight += ancestor.sigop_adjusted_weight;
total_sigop_adjusted_vsize += ancestor.sigop_adjusted_vsize; total_sigop_adjusted_vsize += ancestor.sigop_adjusted_vsize;
total_sigops += ancestor.sigops; total_sigops += ancestor.sigops;
} }
@ -330,7 +330,7 @@ fn set_relatives(txid: u32, audit_pool: &mut AuditPool) {
tx.set_ancestors( tx.set_ancestors(
ancestors, ancestors,
total_fee, total_fee,
total_weight, total_sigop_adjusted_weight,
total_sigop_adjusted_vsize, total_sigop_adjusted_vsize,
total_sigops, total_sigops,
); );
@ -347,7 +347,7 @@ fn update_descendants(
let mut visited: HashSet<u32, U32HasherState> = u32hashset_new(); let mut visited: HashSet<u32, U32HasherState> = u32hashset_new();
let mut descendant_stack: Vec<u32> = Vec::new(); let mut descendant_stack: Vec<u32> = Vec::new();
let root_fee: u64; let root_fee: u64;
let root_weight: u32; let root_sigop_adjusted_weight: u32;
let root_sigop_adjusted_vsize: u32; let root_sigop_adjusted_vsize: u32;
let root_sigops: u32; let root_sigops: u32;
if let Some(root_tx) = audit_pool.get(&root_txid) { if let Some(root_tx) = audit_pool.get(&root_txid) {
@ -358,7 +358,7 @@ fn update_descendants(
} }
} }
root_fee = root_tx.fee; root_fee = root_tx.fee;
root_weight = root_tx.weight; root_sigop_adjusted_weight = root_tx.sigop_adjusted_weight;
root_sigop_adjusted_vsize = root_tx.sigop_adjusted_vsize; root_sigop_adjusted_vsize = root_tx.sigop_adjusted_vsize;
root_sigops = root_tx.sigops; root_sigops = root_tx.sigops;
} else { } else {
@ -370,7 +370,7 @@ fn update_descendants(
let old_score = descendant.remove_root( let old_score = descendant.remove_root(
root_txid, root_txid,
root_fee, root_fee,
root_weight, root_sigop_adjusted_weight,
root_sigop_adjusted_vsize, root_sigop_adjusted_vsize,
root_sigops, root_sigops,
cluster_rate, cluster_rate,