Skip to content

Commit

Permalink
feat: add fee per gram stats to ffi library
Browse files Browse the repository at this point in the history
  • Loading branch information
Cifko committed May 19, 2022
1 parent 50993a3 commit ea74174
Show file tree
Hide file tree
Showing 11 changed files with 4,413 additions and 268 deletions.
23 changes: 11 additions & 12 deletions base_layer/core/src/mempool/unconfirmed_pool/unconfirmed_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,8 +564,7 @@ impl UnconfirmedPool {
let mut total_fees = MicroTari::zero();
let mut min_fee_per_gram = MicroTari::from(u64::MAX);
let mut max_fee_per_gram = MicroTari::zero();
let mut last_count = 0;
for (i, key) in self.tx_by_priority.values().rev().enumerate().skip(offset) {
for key in self.tx_by_priority.values().rev().skip(offset) {
let tx = self.tx_by_key.get(key).ok_or(UnconfirmedPoolError::StorageOutofSync)?;
let weight = tx.weight;

Expand All @@ -574,23 +573,23 @@ impl UnconfirmedPool {
}

let total_tx_fee = tx.transaction.body.get_total_fee();
last_count = i + 1;
offset += 1;
let fee_per_gram = total_tx_fee / weight;
min_fee_per_gram = min_fee_per_gram.min(fee_per_gram);
max_fee_per_gram = max_fee_per_gram.max(fee_per_gram);
total_fees += total_tx_fee;
total_weight += weight;
}
if last_count > 0 {
let stat = FeePerGramStat {
order: start as u64,
min_fee_per_gram,
avg_fee_per_gram: total_fees / total_weight,
max_fee_per_gram,
};
stats.push(stat);
if total_weight == 0 {
break;
}
offset = last_count;
let stat = FeePerGramStat {
order: start as u64,
min_fee_per_gram,
avg_fee_per_gram: total_fees / total_weight,
max_fee_per_gram,
};
stats.push(stat);
}

Ok(stats)
Expand Down
274 changes: 274 additions & 0 deletions base_layer/wallet_ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ pub struct TariContacts(Vec<TariContact>);
pub type TariContact = tari_wallet::contacts_service::storage::database::Contact;
pub type TariCompletedTransaction = tari_wallet::transaction_service::storage::models::CompletedTransaction;
pub type TariTransactionSendStatus = tari_wallet::transaction_service::handle::TransactionSendStatus;
pub type TariFeePerGramStats = tari_wallet::transaction_service::handle::FeePerGramStatsResponse;
pub type TariFeePerGramStat = tari_core::mempool::FeePerGramStat;
pub type TariContactsLivenessData = tari_wallet::contacts_service::handle::ContactsLivenessData;
pub type TariBalance = tari_wallet::output_manager_service::service::Balance;
pub type TariMnemonicLanguage = tari_key_manager::mnemonic::MnemonicLanguage;
Expand Down Expand Up @@ -6430,6 +6432,278 @@ pub unsafe extern "C" fn log_debug_message(msg: *const c_char, error_out: *mut c
}
}

/// ------------------------------------- FeePerGramStats ------------------------------------ ///
/// Get the TariFeePerGramStats from a TariWallet.
///
/// ## Arguments
/// `wallet` - The TariWallet pointer
/// `count` - The maximum number of blocks to be checked
/// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions
/// as an out parameter
///
/// ## Returns
/// `*mut TariCompletedTransactions` - returns the transactions, note that it returns ptr::null_mut() if
/// wallet is null or an error is encountered.
///
/// # Safety
/// The ```fee_per_gram_stats_destroy``` method must be called when finished with a TariFeePerGramStats to prevent
/// a memory leak.
#[no_mangle]
pub unsafe extern "C" fn wallet_get_fee_per_gram_stats(
wallet: *mut TariWallet,
count: c_uint,
error_out: *mut c_int,
) -> *mut TariFeePerGramStats {
let mut error = 0;
ptr::swap(error_out, &mut error as *mut c_int);

if wallet.is_null() {
error = LibWalletError::from(InterfaceError::NullError("wallet".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
return ptr::null_mut();
}

match (*wallet).runtime.block_on(
(*wallet)
.wallet
.transaction_service
.get_fee_per_gram_stats_per_block(count as usize),
) {
Ok(estimates) => Box::into_raw(Box::new(estimates)),
Err(e) => {
error!(target: LOG_TARGET, "Error getting the fee estimates: {:?}", e);
error = LibWalletError::from(WalletError::TransactionServiceError(e)).code;
ptr::swap(error_out, &mut error as *mut c_int);
ptr::null_mut()
},
}
}

/// Get length of stats from the TariFeePerGramStats.
///
/// ## Arguments
/// `fee_per_gram_stats` - The pointer to a TariFeePerGramStats
/// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions
/// as an out parameter
///
/// ## Returns
/// `c_uint` - length of stats in TariFeePerGramStats
///
/// # Safety
/// None
#[no_mangle]
pub unsafe extern "C" fn fee_per_gram_stats_get_length(
fee_per_gram_stats: *mut TariFeePerGramStats,
error_out: *mut c_int,
) -> c_uint {
let mut error = 0;
ptr::swap(error_out, &mut error as *mut c_int);
let mut len = 0;
if fee_per_gram_stats.is_null() {
error = LibWalletError::from(InterfaceError::NullError("fee_per_gram_stats".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
} else {
len = (*fee_per_gram_stats).stats.len();
}
len as c_uint
}

/// Get TariFeePerGramStat at position from the TariFeePerGramStats.
///
/// ## Arguments
/// `fee_per_gram_stats` - The pointer to a TariFeePerGramStats.
/// `position` - The integer position.
/// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions
/// as an out parameter.
///
/// ## Returns
/// `*mut TariCompletedTransactions` - returns the TariFeePerGramStat, note that it returns ptr::null_mut() if
/// fee_per_gram_stats is null or an error is encountered.
///
/// # Safety
/// The ```fee_per_gram_stat_destroy``` method must be called when finished with a TariCompletedTransactions to 4prevent
/// a memory leak.
#[no_mangle]
pub unsafe extern "C" fn fee_per_gram_stats_get_at(
fee_per_gram_stats: *mut TariFeePerGramStats,
position: c_uint,
error_out: *mut c_int,
) -> *mut TariFeePerGramStat {
let mut error = 0;
ptr::swap(error_out, &mut error as *mut c_int);
if fee_per_gram_stats.is_null() {
error = LibWalletError::from(InterfaceError::NullError("fee_per_gram_stats".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
return ptr::null_mut();
}
let len = fee_per_gram_stats_get_length(fee_per_gram_stats, error_out);
if *error_out != 0 {
return ptr::null_mut();
}
if len == 0 || position > len - 1 {
error = LibWalletError::from(InterfaceError::PositionInvalidError).code;
ptr::swap(error_out, &mut error as *mut c_int);
return ptr::null_mut();
}
Box::into_raw(Box::new((*fee_per_gram_stats).stats[position as usize].clone()))
}

/// Frees memory for a TariFeePerGramStats
///
/// ## Arguments
/// `fee_per_gram_stats` - The TariFeePerGramStats pointer
///
/// ## Returns
/// `()` - Does not return a value, equivalent to void in C
///
/// # Safety
/// None
#[no_mangle]
pub unsafe extern "C" fn fee_per_gram_stats_destroy(fee_per_gram_stats: *mut TariFeePerGramStats) {
if !fee_per_gram_stats.is_null() {
Box::from_raw(fee_per_gram_stats);
}
}

/// ------------------------------------------------------------------------------------------ ///
/// ------------------------------------- FeePerGramStat ------------------------------------- ///
/// Get the order of TariFeePerGramStat
///
/// ## Arguments
/// `fee_per_gram_stats` - The TariFeePerGramStat pointer
/// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions
/// as an out parameter.
///
/// ## Returns
/// `c_ulonglong` - Returns order
///
/// # Safety
/// None
#[no_mangle]
pub unsafe extern "C" fn fee_per_gram_stat_get_order(
fee_per_gram_stat: *mut TariFeePerGramStat,
error_out: *mut c_int,
) -> c_ulonglong {
let mut error = 0;
ptr::swap(error_out, &mut error as *mut c_int);
let mut order = 0;
if fee_per_gram_stat.is_null() {
error = LibWalletError::from(InterfaceError::NullError("fee_per_gram_stat".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
} else {
order = (*fee_per_gram_stat).order;
}
order
}

/// Get the minimum fee per gram of TariFeePerGramStat
///
/// ## Arguments
/// `fee_per_gram_stats` - The TariFeePerGramStat pointer
/// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions
/// as an out parameter.
///
/// ## Returns
/// `c_ulonglong` - Returns minimum fee per gram
///
/// # Safety
/// None
#[no_mangle]
pub unsafe extern "C" fn fee_per_gram_stat_get_min_fee_per_gram(
fee_per_gram_stat: *mut TariFeePerGramStat,
error_out: *mut c_int,
) -> c_ulonglong {
let mut error = 0;
ptr::swap(error_out, &mut error as *mut c_int);
let mut fee_per_gram = 0;
if fee_per_gram_stat.is_null() {
error = LibWalletError::from(InterfaceError::NullError("fee_per_gram_stat".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
} else {
fee_per_gram = (*fee_per_gram_stat).min_fee_per_gram.as_u64();
}
fee_per_gram
}

/// Get the average fee per gram of TariFeePerGramStat
///
/// ## Arguments
/// `fee_per_gram_stats` - The TariFeePerGramStat pointer
/// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions
/// as an out parameter.
///
/// ## Returns
/// `c_ulonglong` - Returns average fee per gram
///
/// # Safety
/// None
#[no_mangle]
pub unsafe extern "C" fn fee_per_gram_stat_get_avg_fee_per_gram(
fee_per_gram_stat: *mut TariFeePerGramStat,
error_out: *mut c_int,
) -> c_ulonglong {
let mut error = 0;
ptr::swap(error_out, &mut error as *mut c_int);
let mut fee_per_gram = 0;
if fee_per_gram_stat.is_null() {
error = LibWalletError::from(InterfaceError::NullError("fee_per_gram_stat".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
} else {
fee_per_gram = (*fee_per_gram_stat).avg_fee_per_gram.as_u64();
}
fee_per_gram
}

/// Get the maximum fee per gram of TariFeePerGramStat
///
/// ## Arguments
/// `fee_per_gram_stats` - The TariFeePerGramStat pointer
/// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions
/// as an out parameter.
///
/// ## Returns
/// `c_ulonglong` - Returns maximum fee per gram
///
/// # Safety
/// None
#[no_mangle]
pub unsafe extern "C" fn fee_per_gram_stat_get_max_fee_per_gram(
fee_per_gram_stat: *mut TariFeePerGramStat,
error_out: *mut c_int,
) -> c_ulonglong {
let mut error = 0;
ptr::swap(error_out, &mut error as *mut c_int);
let mut fee_per_gram = 0;
if fee_per_gram_stat.is_null() {
error = LibWalletError::from(InterfaceError::NullError("fee_per_gram_stat".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
} else {
fee_per_gram = (*fee_per_gram_stat).max_fee_per_gram.as_u64();
}
fee_per_gram
}

/// Frees memory for a TariFeePerGramStat
///
/// ## Arguments
/// `fee_per_gram_stats` - The TariFeePerGramStat pointer
///
/// ## Returns
/// `()` - Does not return a value, equivalent to void in C
///
/// # Safety
/// None
#[no_mangle]
pub unsafe extern "C" fn fee_per_gram_stat_destroy(fee_per_gram_stat: *mut TariFeePerGramStat) {
if !fee_per_gram_stat.is_null() {
Box::from_raw(fee_per_gram_stat);
}
}

/// ------------------------------------------------------------------------------------------ ///
#[cfg(test)]
mod test {
use std::{
Expand Down
4 changes: 4 additions & 0 deletions base_layer/wallet_ffi/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ struct EmojiSet;

struct TariTransactionKernel;

struct TariFeePerGramStatsResponse;

/// -------------------------------- Transport Types ----------------------------------------------- ///

// Creates a memory transport type
Expand Down Expand Up @@ -868,6 +870,8 @@ bool wallet_start_recovery(struct TariWallet *wallet, struct TariPublicKey *base
/// None
bool wallet_set_one_sided_payment_message(struct TariWallet *wallet, const char *message, int *error_out);

struct TariFeePerGramStatsResponse *wallet_get_fee_estimates_per_block(struct TariWallet *wallet, unsigned int count, int *error_out);

// Frees memory for a TariWallet
void wallet_destroy(struct TariWallet *wallet);

Expand Down
Loading

0 comments on commit ea74174

Please sign in to comment.