Add acceleration support to rust gbt
This commit is contained in:
8
backend/rust-gbt/index.d.ts
vendored
8
backend/rust-gbt/index.d.ts
vendored
@@ -12,6 +12,10 @@ export interface ThreadTransaction {
|
||||
effectiveFeePerVsize: number
|
||||
inputs: Array<number>
|
||||
}
|
||||
export interface ThreadAcceleration {
|
||||
uid: number
|
||||
delta: number
|
||||
}
|
||||
export class GbtGenerator {
|
||||
constructor()
|
||||
/**
|
||||
@@ -19,13 +23,13 @@ export class GbtGenerator {
|
||||
*
|
||||
* Rejects if the thread panics or if the Mutex is poisoned.
|
||||
*/
|
||||
make(mempool: Array<ThreadTransaction>, maxUid: number): Promise<GbtResult>
|
||||
make(mempool: Array<ThreadTransaction>, accelerations: Array<ThreadAcceleration>, maxUid: number): Promise<GbtResult>
|
||||
/**
|
||||
* # Errors
|
||||
*
|
||||
* Rejects if the thread panics or if the Mutex is poisoned.
|
||||
*/
|
||||
update(newTxs: Array<ThreadTransaction>, removeTxs: Array<number>, maxUid: number): Promise<GbtResult>
|
||||
update(newTxs: Array<ThreadTransaction>, removeTxs: Array<number>, accelerations: Array<ThreadAcceleration>, maxUid: number): Promise<GbtResult>
|
||||
}
|
||||
/**
|
||||
* The result from calling the gbt function.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
u32_hasher_types::{u32hashset_new, U32HasherState},
|
||||
ThreadTransaction,
|
||||
ThreadTransaction, thread_acceleration::ThreadAcceleration,
|
||||
};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
@@ -88,37 +88,42 @@ impl Ord for AuditTransaction {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn calc_fee_rate(fee: f64, vsize: f64) -> f64 {
|
||||
fee / (if vsize == 0.0 { 1.0 } else { vsize })
|
||||
fn calc_fee_rate(fee: u64, vsize: f64) -> f64 {
|
||||
(fee as f64) / (if vsize == 0.0 { 1.0 } else { vsize })
|
||||
}
|
||||
|
||||
impl AuditTransaction {
|
||||
pub fn from_thread_transaction(tx: &ThreadTransaction) -> Self {
|
||||
pub fn from_thread_transaction(tx: &ThreadTransaction, maybe_acceleration: Option<Option<&ThreadAcceleration>>) -> Self {
|
||||
let fee_delta = match maybe_acceleration {
|
||||
Some(Some(acceleration)) => acceleration.delta,
|
||||
_ => 0.0
|
||||
};
|
||||
let fee = (tx.fee as u64) + (fee_delta as u64);
|
||||
// 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_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)
|
||||
let effective_fee_per_vsize = if is_adjusted || fee_delta > 0.0 {
|
||||
calc_fee_rate(fee, f64::from(sigop_adjusted_weight) / 4.0)
|
||||
} else {
|
||||
tx.effective_fee_per_vsize
|
||||
};
|
||||
Self {
|
||||
uid: tx.uid,
|
||||
order: tx.order,
|
||||
fee: tx.fee as u64,
|
||||
fee,
|
||||
weight: tx.weight,
|
||||
sigop_adjusted_weight,
|
||||
sigop_adjusted_vsize,
|
||||
sigops: tx.sigops,
|
||||
adjusted_fee_per_vsize: calc_fee_rate(tx.fee, f64::from(sigop_adjusted_vsize)),
|
||||
adjusted_fee_per_vsize: calc_fee_rate(fee, f64::from(sigop_adjusted_vsize)),
|
||||
effective_fee_per_vsize,
|
||||
dependency_rate: f64::INFINITY,
|
||||
inputs: tx.inputs.clone(),
|
||||
relatives_set_flag: false,
|
||||
ancestors: u32hashset_new(),
|
||||
children: u32hashset_new(),
|
||||
ancestor_fee: tx.fee as u64,
|
||||
ancestor_fee: fee,
|
||||
ancestor_sigop_adjusted_weight: sigop_adjusted_weight,
|
||||
ancestor_sigop_adjusted_vsize: sigop_adjusted_vsize,
|
||||
ancestor_sigops: tx.sigops,
|
||||
@@ -156,7 +161,7 @@ impl AuditTransaction {
|
||||
// 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.
|
||||
self.dependency_rate.min(calc_fee_rate(
|
||||
self.ancestor_fee as f64,
|
||||
self.ancestor_fee,
|
||||
f64::from(self.ancestor_sigop_adjusted_weight) / 4.0,
|
||||
))
|
||||
}
|
||||
@@ -172,7 +177,7 @@ impl AuditTransaction {
|
||||
#[inline]
|
||||
fn calc_new_score(&mut self) {
|
||||
self.score = self.adjusted_fee_per_vsize.min(calc_fee_rate(
|
||||
self.ancestor_fee as f64,
|
||||
self.ancestor_fee,
|
||||
f64::from(self.ancestor_sigop_adjusted_vsize),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use tracing::{info, trace};
|
||||
use crate::{
|
||||
audit_transaction::{partial_cmp_uid_score, AuditTransaction},
|
||||
u32_hasher_types::{u32hashset_new, u32priority_queue_with_capacity, U32HasherState},
|
||||
GbtResult, ThreadTransactionsMap,
|
||||
GbtResult, ThreadTransactionsMap, thread_acceleration::ThreadAcceleration,
|
||||
};
|
||||
|
||||
const MAX_BLOCK_WEIGHT_UNITS: u32 = 4_000_000 - 4_000;
|
||||
@@ -53,7 +53,13 @@ impl Ord for TxPriority {
|
||||
// TODO: Make gbt smaller to fix these lints.
|
||||
#[allow(clippy::too_many_lines)]
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
pub fn gbt(mempool: &mut ThreadTransactionsMap, max_uid: usize) -> GbtResult {
|
||||
pub fn gbt(mempool: &mut ThreadTransactionsMap, accelerations: &[ThreadAcceleration], max_uid: usize) -> GbtResult {
|
||||
let mut indexed_accelerations = Vec::with_capacity(max_uid + 1);
|
||||
indexed_accelerations.resize(max_uid + 1, None);
|
||||
for acceleration in accelerations {
|
||||
indexed_accelerations[acceleration.uid as usize] = Some(acceleration);
|
||||
}
|
||||
|
||||
let mempool_len = mempool.len();
|
||||
let mut audit_pool: AuditPool = Vec::with_capacity(max_uid + 1);
|
||||
audit_pool.resize(max_uid + 1, None);
|
||||
@@ -63,7 +69,8 @@ pub fn gbt(mempool: &mut ThreadTransactionsMap, max_uid: usize) -> GbtResult {
|
||||
|
||||
info!("Initializing working structs");
|
||||
for (uid, tx) in &mut *mempool {
|
||||
let audit_tx = AuditTransaction::from_thread_transaction(tx);
|
||||
let acceleration = indexed_accelerations.get(*uid as usize);
|
||||
let audit_tx = AuditTransaction::from_thread_transaction(tx, acceleration.copied());
|
||||
// Safety: audit_pool and mempool_stack must always contain the same transactions
|
||||
audit_pool[*uid as usize] = Some(ManuallyDrop::new(audit_tx));
|
||||
mempool_stack.push(*uid);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
use napi::bindgen_prelude::Result;
|
||||
use napi_derive::napi;
|
||||
use thread_transaction::ThreadTransaction;
|
||||
use thread_acceleration::ThreadAcceleration;
|
||||
use tracing::{debug, info, trace};
|
||||
use tracing_log::LogTracer;
|
||||
use tracing_subscriber::{EnvFilter, FmtSubscriber};
|
||||
@@ -19,6 +20,7 @@ use std::sync::{Arc, Mutex};
|
||||
mod audit_transaction;
|
||||
mod gbt;
|
||||
mod thread_transaction;
|
||||
mod thread_acceleration;
|
||||
mod u32_hasher_types;
|
||||
|
||||
use u32_hasher_types::{u32hashmap_with_capacity, U32HasherState};
|
||||
@@ -74,10 +76,11 @@ impl GbtGenerator {
|
||||
///
|
||||
/// Rejects if the thread panics or if the Mutex is poisoned.
|
||||
#[napi]
|
||||
pub async fn make(&self, mempool: Vec<ThreadTransaction>, max_uid: u32) -> Result<GbtResult> {
|
||||
pub async fn make(&self, mempool: Vec<ThreadTransaction>, accelerations: Vec<ThreadAcceleration>, max_uid: u32) -> Result<GbtResult> {
|
||||
trace!("make: Current State {:#?}", self.thread_transactions);
|
||||
run_task(
|
||||
Arc::clone(&self.thread_transactions),
|
||||
accelerations,
|
||||
max_uid as usize,
|
||||
move |map| {
|
||||
for tx in mempool {
|
||||
@@ -96,11 +99,13 @@ impl GbtGenerator {
|
||||
&self,
|
||||
new_txs: Vec<ThreadTransaction>,
|
||||
remove_txs: Vec<u32>,
|
||||
accelerations: Vec<ThreadAcceleration>,
|
||||
max_uid: u32,
|
||||
) -> Result<GbtResult> {
|
||||
trace!("update: Current State {:#?}", self.thread_transactions);
|
||||
run_task(
|
||||
Arc::clone(&self.thread_transactions),
|
||||
accelerations,
|
||||
max_uid as usize,
|
||||
move |map| {
|
||||
for tx in new_txs {
|
||||
@@ -141,6 +146,7 @@ pub struct GbtResult {
|
||||
/// to the `HashMap` as the only argument. (A move closure is recommended to meet the bounds)
|
||||
async fn run_task<F>(
|
||||
thread_transactions: Arc<Mutex<ThreadTransactionsMap>>,
|
||||
accelerations: Vec<ThreadAcceleration>,
|
||||
max_uid: usize,
|
||||
callback: F,
|
||||
) -> Result<GbtResult>
|
||||
@@ -159,7 +165,7 @@ where
|
||||
callback(&mut map);
|
||||
|
||||
info!("Starting gbt algorithm for {} elements...", map.len());
|
||||
let result = gbt::gbt(&mut map, max_uid);
|
||||
let result = gbt::gbt(&mut map, &accelerations, max_uid);
|
||||
info!("Finished gbt algorithm for {} elements...", map.len());
|
||||
|
||||
debug!(
|
||||
|
||||
Reference in New Issue
Block a user