conform to core's gbt quirks
This commit is contained in:
		
							parent
							
								
									71f150b587
								
							
						
					
					
						commit
						10beb76585
					
				@ -14,6 +14,7 @@ pub struct AuditTransaction {
 | 
			
		||||
    pub uid: u32,
 | 
			
		||||
    pub fee: u64,
 | 
			
		||||
    pub weight: u32,
 | 
			
		||||
    pub vsize: u32,
 | 
			
		||||
    pub sigops: u32,
 | 
			
		||||
    pub fee_per_vsize: f64,
 | 
			
		||||
    pub effective_fee_per_vsize: f64,
 | 
			
		||||
@ -24,6 +25,7 @@ pub struct AuditTransaction {
 | 
			
		||||
    pub children: HashSet<u32, U32HasherState>,
 | 
			
		||||
    ancestor_fee: u64,
 | 
			
		||||
    ancestor_weight: u32,
 | 
			
		||||
    ancestor_vsize: u32,
 | 
			
		||||
    ancestor_sigops: u32,
 | 
			
		||||
    // Safety: Must be private to prevent NaN breaking Ord impl.
 | 
			
		||||
    score: f64,
 | 
			
		||||
@ -74,6 +76,7 @@ impl AuditTransaction {
 | 
			
		||||
            uid: tx.uid,
 | 
			
		||||
            fee: tx.fee,
 | 
			
		||||
            weight: tx.weight,
 | 
			
		||||
            vsize: ((tx.weight + 3) / 4).max(tx.sigops * 5), // rounded up to the nearest integer
 | 
			
		||||
            sigops: tx.sigops,
 | 
			
		||||
            fee_per_vsize: tx.fee_per_vsize,
 | 
			
		||||
            effective_fee_per_vsize: tx.effective_fee_per_vsize,
 | 
			
		||||
@ -84,6 +87,7 @@ impl AuditTransaction {
 | 
			
		||||
            children: u32hashset_new(),
 | 
			
		||||
            ancestor_fee: tx.fee,
 | 
			
		||||
            ancestor_weight: tx.weight,
 | 
			
		||||
            ancestor_vsize: ((tx.weight + 3) / 4).max(tx.sigops * 5), // rounded up to the nearest integer
 | 
			
		||||
            ancestor_sigops: tx.sigops,
 | 
			
		||||
            score: 0.0,
 | 
			
		||||
            used: false,
 | 
			
		||||
@ -98,8 +102,8 @@ impl AuditTransaction {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub const fn ancestor_weight(&self) -> u32 {
 | 
			
		||||
        self.ancestor_weight
 | 
			
		||||
    pub const fn ancestor_vsize(&self) -> u32 {
 | 
			
		||||
        self.ancestor_vsize
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
@ -128,10 +132,10 @@ impl AuditTransaction {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn calc_new_score(&mut self) {
 | 
			
		||||
        self.score = (self.ancestor_fee as f64)
 | 
			
		||||
            / (if self.ancestor_weight == 0 {
 | 
			
		||||
            / (if self.ancestor_vsize == 0 {
 | 
			
		||||
                1.0
 | 
			
		||||
            } else {
 | 
			
		||||
                f64::from(self.ancestor_weight) / 4.0
 | 
			
		||||
                f64::from(self.ancestor_vsize)
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -141,11 +145,13 @@ impl AuditTransaction {
 | 
			
		||||
        ancestors: HashSet<u32, U32HasherState>,
 | 
			
		||||
        total_fee: u64,
 | 
			
		||||
        total_weight: u32,
 | 
			
		||||
        total_vsize: u32,
 | 
			
		||||
        total_sigops: u32,
 | 
			
		||||
    ) {
 | 
			
		||||
        self.ancestors = ancestors;
 | 
			
		||||
        self.ancestor_fee = self.fee + total_fee;
 | 
			
		||||
        self.ancestor_weight = self.weight + total_weight;
 | 
			
		||||
        self.ancestor_vsize = self.vsize + total_vsize;
 | 
			
		||||
        self.ancestor_sigops = self.sigops + total_sigops;
 | 
			
		||||
        self.calc_new_score();
 | 
			
		||||
        self.relatives_set_flag = true;
 | 
			
		||||
@ -157,6 +163,7 @@ impl AuditTransaction {
 | 
			
		||||
        root_txid: u32,
 | 
			
		||||
        root_fee: u64,
 | 
			
		||||
        root_weight: u32,
 | 
			
		||||
        root_vsize: u32,
 | 
			
		||||
        root_sigops: u32,
 | 
			
		||||
        cluster_rate: f64,
 | 
			
		||||
    ) -> f64 {
 | 
			
		||||
@ -165,6 +172,7 @@ impl AuditTransaction {
 | 
			
		||||
        if self.ancestors.remove(&root_txid) {
 | 
			
		||||
            self.ancestor_fee -= root_fee;
 | 
			
		||||
            self.ancestor_weight -= root_weight;
 | 
			
		||||
            self.ancestor_vsize -= root_vsize;
 | 
			
		||||
            self.ancestor_sigops -= root_sigops;
 | 
			
		||||
            self.calc_new_score();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -13,9 +13,10 @@ use crate::{
 | 
			
		||||
    GbtResult, ThreadTransactionsMap, STARTING_CAPACITY,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const BLOCK_WEIGHT_UNITS: u32 = 4_000_000;
 | 
			
		||||
const MAX_BLOCK_WEIGHT_UNITS: u32 = 4_000_000 - 4_000;
 | 
			
		||||
const BLOCK_SIGOPS: u32 = 80_000;
 | 
			
		||||
const BLOCK_RESERVED_WEIGHT: u32 = 4_000;
 | 
			
		||||
const BLOCK_RESERVED_SIGOPS: u32 = 400;
 | 
			
		||||
const MAX_BLOCKS: usize = 8;
 | 
			
		||||
 | 
			
		||||
type AuditPool = HashMap<u32, AuditTransaction, U32HasherState>;
 | 
			
		||||
@ -91,7 +92,7 @@ pub fn gbt(mempool: &mut ThreadTransactionsMap) -> GbtResult {
 | 
			
		||||
    info!("(i.e. the package rooted in the transaction with the best ancestor score)");
 | 
			
		||||
    let mut blocks: Vec<Vec<u32>> = Vec::new();
 | 
			
		||||
    let mut block_weight: u32 = BLOCK_RESERVED_WEIGHT;
 | 
			
		||||
    let mut block_sigops: u32 = 0;
 | 
			
		||||
    let mut block_sigops: u32 = BLOCK_RESERVED_SIGOPS;
 | 
			
		||||
    let mut transactions: Vec<u32> = Vec::with_capacity(STARTING_CAPACITY);
 | 
			
		||||
    let mut modified: ModifiedQueue = u32priority_queue_with_capacity(STARTING_CAPACITY);
 | 
			
		||||
    let mut overflow: Vec<u32> = Vec::new();
 | 
			
		||||
@ -135,7 +136,7 @@ pub fn gbt(mempool: &mut ThreadTransactionsMap) -> GbtResult {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if blocks.len() < (MAX_BLOCKS - 1)
 | 
			
		||||
            && ((block_weight + next_tx.ancestor_weight() >= BLOCK_WEIGHT_UNITS)
 | 
			
		||||
            && ((block_weight + (4 * next_tx.ancestor_vsize()) >= MAX_BLOCK_WEIGHT_UNITS)
 | 
			
		||||
                || (block_sigops + next_tx.ancestor_sigops() > BLOCK_SIGOPS))
 | 
			
		||||
        {
 | 
			
		||||
            // hold this package in an overflow list while we check for smaller options
 | 
			
		||||
@ -150,7 +151,13 @@ pub fn gbt(mempool: &mut ThreadTransactionsMap) -> GbtResult {
 | 
			
		||||
                    package.push((*ancestor_id, ancestor.ancestors.len()));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            package.sort_unstable_by_key(|a| a.1);
 | 
			
		||||
            package.sort_unstable_by(|a, b| -> Ordering {
 | 
			
		||||
                if a.1 == b.1 {
 | 
			
		||||
                    b.0.cmp(&a.0)
 | 
			
		||||
                } else {
 | 
			
		||||
                    a.1.cmp(&b.1)
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            package.push((next_tx.uid, next_tx.ancestors.len()));
 | 
			
		||||
 | 
			
		||||
            let cluster_rate = next_tx.cluster_rate();
 | 
			
		||||
@ -176,7 +183,7 @@ pub fn gbt(mempool: &mut ThreadTransactionsMap) -> GbtResult {
 | 
			
		||||
 | 
			
		||||
        // this block is full
 | 
			
		||||
        let exceeded_package_tries =
 | 
			
		||||
            failures > 1000 && block_weight > (BLOCK_WEIGHT_UNITS - BLOCK_RESERVED_WEIGHT);
 | 
			
		||||
            failures > 1000 && block_weight > (MAX_BLOCK_WEIGHT_UNITS - BLOCK_RESERVED_WEIGHT);
 | 
			
		||||
        let queue_is_empty = mempool_stack.is_empty() && modified.is_empty();
 | 
			
		||||
        if (exceeded_package_tries || queue_is_empty) && blocks.len() < (MAX_BLOCKS - 1) {
 | 
			
		||||
            // finalize this block
 | 
			
		||||
@ -185,8 +192,8 @@ pub fn gbt(mempool: &mut ThreadTransactionsMap) -> GbtResult {
 | 
			
		||||
            }
 | 
			
		||||
            // reset for the next block
 | 
			
		||||
            transactions = Vec::with_capacity(STARTING_CAPACITY);
 | 
			
		||||
            block_weight = 4000;
 | 
			
		||||
            block_sigops = 0;
 | 
			
		||||
            block_weight = BLOCK_RESERVED_WEIGHT;
 | 
			
		||||
            block_sigops = BLOCK_RESERVED_SIGOPS;
 | 
			
		||||
            failures = 0;
 | 
			
		||||
            // 'overflow' packages didn't fit in this block, but are valid candidates for the next
 | 
			
		||||
            overflow.reverse();
 | 
			
		||||
@ -290,6 +297,7 @@ fn set_relatives(txid: u32, audit_pool: &mut AuditPool) {
 | 
			
		||||
 | 
			
		||||
    let mut total_fee: u64 = 0;
 | 
			
		||||
    let mut total_weight: u32 = 0;
 | 
			
		||||
    let mut total_vsize: u32 = 0;
 | 
			
		||||
    let mut total_sigops: u32 = 0;
 | 
			
		||||
 | 
			
		||||
    for ancestor_id in &ancestors {
 | 
			
		||||
@ -298,11 +306,12 @@ fn set_relatives(txid: u32, audit_pool: &mut AuditPool) {
 | 
			
		||||
            .expect("audit_pool contains all ancestors");
 | 
			
		||||
        total_fee += ancestor.fee;
 | 
			
		||||
        total_weight += ancestor.weight;
 | 
			
		||||
        total_vsize += ancestor.vsize;
 | 
			
		||||
        total_sigops += ancestor.sigops;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if let Some(tx) = audit_pool.get_mut(&txid) {
 | 
			
		||||
        tx.set_ancestors(ancestors, total_fee, total_weight, total_sigops);
 | 
			
		||||
        tx.set_ancestors(ancestors, total_fee, total_weight, total_vsize, total_sigops);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -317,6 +326,7 @@ fn update_descendants(
 | 
			
		||||
    let mut descendant_stack: Vec<u32> = Vec::new();
 | 
			
		||||
    let root_fee: u64;
 | 
			
		||||
    let root_weight: u32;
 | 
			
		||||
    let root_vsize: u32;
 | 
			
		||||
    let root_sigops: u32;
 | 
			
		||||
    if let Some(root_tx) = audit_pool.get(&root_txid) {
 | 
			
		||||
        for descendant_id in &root_tx.children {
 | 
			
		||||
@ -327,6 +337,7 @@ fn update_descendants(
 | 
			
		||||
        }
 | 
			
		||||
        root_fee = root_tx.fee;
 | 
			
		||||
        root_weight = root_tx.weight;
 | 
			
		||||
        root_vsize = root_tx.vsize;
 | 
			
		||||
        root_sigops = root_tx.sigops;
 | 
			
		||||
    } else {
 | 
			
		||||
        return;
 | 
			
		||||
@ -335,7 +346,7 @@ fn update_descendants(
 | 
			
		||||
        if let Some(descendant) = audit_pool.get_mut(&next_txid) {
 | 
			
		||||
            // remove root tx as ancestor
 | 
			
		||||
            let old_score =
 | 
			
		||||
                descendant.remove_root(root_txid, root_fee, root_weight, root_sigops, cluster_rate);
 | 
			
		||||
                descendant.remove_root(root_txid, root_fee, root_weight, root_vsize, root_sigops, cluster_rate);
 | 
			
		||||
            // add to priority queue or update priority if score has changed
 | 
			
		||||
            if descendant.score() < old_score {
 | 
			
		||||
                descendant.modified = true;
 | 
			
		||||
 | 
			
		||||
@ -657,7 +657,7 @@ class MempoolBlocks {
 | 
			
		||||
      if (tx.uid !== null && tx.uid !== undefined) {
 | 
			
		||||
        view.setUint32(offset, tx.uid, false);
 | 
			
		||||
        view.setFloat64(offset + 4, tx.fee, false);
 | 
			
		||||
        view.setUint32(offset + 12, (tx.adjustedVsize * 4), false);
 | 
			
		||||
        view.setUint32(offset + 12, tx.weight, false);
 | 
			
		||||
        view.setUint32(offset + 16, tx.sigops, false);
 | 
			
		||||
        view.setFloat64(offset + 20, (tx.adjustedFeePerVsize || tx.feePerVsize), false);
 | 
			
		||||
        view.setFloat64(offset + 28, (tx.effectiveFeePerVsize || tx.adjustedFeePerVsize || tx.feePerVsize), false);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user