mirror of
https://github.com/monero-project/monero.git
synced 2025-08-23 07:05:08 -04:00
Fee changes from ArticMine
https://github.com/ArticMine/Monero-Documents/blob/master/MoneroScaling2021-02.pdf with a change to use 1.7 instead of 2.0 for the max long term increase rate
This commit is contained in:
parent
9f786f0550
commit
b030f20751
15 changed files with 498 additions and 48 deletions
|
@ -290,15 +290,15 @@ void do_prepare_file_names(const std::string& file_path, std::string& keys_file,
|
|||
mms_file = file_path + ".mms";
|
||||
}
|
||||
|
||||
uint64_t calculate_fee(uint64_t fee_per_kb, size_t bytes, uint64_t fee_multiplier)
|
||||
uint64_t calculate_fee(uint64_t fee_per_kb, size_t bytes)
|
||||
{
|
||||
uint64_t kB = (bytes + 1023) / 1024;
|
||||
return kB * fee_per_kb * fee_multiplier;
|
||||
return kB * fee_per_kb;
|
||||
}
|
||||
|
||||
uint64_t calculate_fee_from_weight(uint64_t base_fee, uint64_t weight, uint64_t fee_multiplier, uint64_t fee_quantization_mask)
|
||||
uint64_t calculate_fee_from_weight(uint64_t base_fee, uint64_t weight, uint64_t fee_quantization_mask)
|
||||
{
|
||||
uint64_t fee = weight * base_fee * fee_multiplier;
|
||||
uint64_t fee = weight * base_fee;
|
||||
fee = (fee + fee_quantization_mask - 1) / fee_quantization_mask * fee_quantization_mask;
|
||||
return fee;
|
||||
}
|
||||
|
@ -878,12 +878,12 @@ uint8_t get_clsag_fork()
|
|||
return HF_VERSION_CLSAG;
|
||||
}
|
||||
|
||||
uint64_t calculate_fee(bool use_per_byte_fee, const cryptonote::transaction &tx, size_t blob_size, uint64_t base_fee, uint64_t fee_multiplier, uint64_t fee_quantization_mask)
|
||||
uint64_t calculate_fee(bool use_per_byte_fee, const cryptonote::transaction &tx, size_t blob_size, uint64_t base_fee, uint64_t fee_quantization_mask)
|
||||
{
|
||||
if (use_per_byte_fee)
|
||||
return calculate_fee_from_weight(base_fee, cryptonote::get_transaction_weight(tx, blob_size), fee_multiplier, fee_quantization_mask);
|
||||
return calculate_fee_from_weight(base_fee, cryptonote::get_transaction_weight(tx, blob_size), fee_quantization_mask);
|
||||
else
|
||||
return calculate_fee(base_fee, blob_size, fee_multiplier);
|
||||
return calculate_fee(base_fee, blob_size);
|
||||
}
|
||||
|
||||
bool get_short_payment_id(crypto::hash8 &payment_id8, const tools::wallet2::pending_tx &ptx, hw::device &hwdev)
|
||||
|
@ -7232,17 +7232,17 @@ bool wallet2::sign_multisig_tx_from_file(const std::string &filename, std::vecto
|
|||
return sign_multisig_tx_to_file(exported_txs, filename, txids);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, uint64_t base_fee, uint64_t fee_multiplier, uint64_t fee_quantization_mask) const
|
||||
uint64_t wallet2::estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, uint64_t base_fee, uint64_t fee_quantization_mask) const
|
||||
{
|
||||
if (use_per_byte_fee)
|
||||
{
|
||||
const size_t estimated_tx_weight = estimate_tx_weight(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus);
|
||||
return calculate_fee_from_weight(base_fee, estimated_tx_weight, fee_multiplier, fee_quantization_mask);
|
||||
return calculate_fee_from_weight(base_fee, estimated_tx_weight, fee_quantization_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t estimated_tx_size = estimate_tx_size(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus);
|
||||
return calculate_fee(base_fee, estimated_tx_size, fee_multiplier);
|
||||
return calculate_fee(base_fee, estimated_tx_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7315,6 +7315,40 @@ uint64_t wallet2::get_base_fee()
|
|||
return get_dynamic_base_fee_estimate();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::get_base_fee(uint32_t priority)
|
||||
{
|
||||
const bool use_2021_scaling = use_fork_rules(HF_VERSION_2021_SCALING, -30 * 1);
|
||||
if (use_2021_scaling)
|
||||
{
|
||||
// clamp and map to 0..3 indices, mapping 0 (default, but should not end up here) to 0, and 1..4 to 0..3
|
||||
if (priority == 0)
|
||||
priority = 1;
|
||||
else if (priority > 4)
|
||||
priority = 4;
|
||||
--priority;
|
||||
|
||||
std::vector<uint64_t> fees;
|
||||
boost::optional<std::string> result = m_node_rpc_proxy.get_dynamic_base_fee_estimate_2021_scaling(FEE_ESTIMATE_GRACE_BLOCKS, fees);
|
||||
if (result)
|
||||
{
|
||||
MERROR("Failed to determine base fee, using default");
|
||||
return FEE_PER_BYTE;
|
||||
}
|
||||
if (priority >= fees.size())
|
||||
{
|
||||
MERROR("Failed to determine base fee for priority " << priority << ", using default");
|
||||
return FEE_PER_BYTE;
|
||||
}
|
||||
return fees[priority];
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint64_t base_fee = get_base_fee();
|
||||
const uint64_t fee_multiplier = get_fee_multiplier(priority);
|
||||
return base_fee * fee_multiplier;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::get_fee_quantization_mask()
|
||||
{
|
||||
if(m_light_wallet)
|
||||
|
@ -7389,9 +7423,8 @@ uint32_t wallet2::adjust_priority(uint32_t priority)
|
|||
{
|
||||
// check if there's a backlog in the tx pool
|
||||
const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0);
|
||||
const uint64_t base_fee = get_base_fee();
|
||||
const uint64_t fee_multiplier = get_fee_multiplier(1);
|
||||
const double fee_level = fee_multiplier * base_fee * (use_per_byte_fee ? 1 : (12/(double)13 / (double)1024));
|
||||
const uint64_t base_fee = get_base_fee(1);
|
||||
const double fee_level = base_fee * (use_per_byte_fee ? 1 : (12/(double)13 / (double)1024));
|
||||
const std::vector<std::pair<uint64_t, uint64_t>> blocks = estimate_backlog({std::make_pair(fee_level, fee_level)});
|
||||
if (blocks.size() != 1)
|
||||
{
|
||||
|
@ -9665,8 +9698,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
bulletproof_plus ? 4 : 3
|
||||
};
|
||||
|
||||
const uint64_t base_fee = get_base_fee();
|
||||
const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm());
|
||||
const uint64_t base_fee = get_base_fee(priority);
|
||||
const uint64_t fee_quantization_mask = get_fee_quantization_mask();
|
||||
|
||||
// throw if attempting a transaction with no destinations
|
||||
|
@ -9698,7 +9730,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
// early out if we know we can't make it anyway
|
||||
// we could also check for being within FEE_PER_KB, but if the fee calculation
|
||||
// ever changes, this might be missed, so let this go through
|
||||
const uint64_t min_fee = (fee_multiplier * base_fee * estimate_tx_size(use_rct, 1, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus));
|
||||
const uint64_t min_fee = (base_fee * estimate_tx_size(use_rct, 1, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus));
|
||||
uint64_t balance_subtotal = 0;
|
||||
uint64_t unlocked_balance_subtotal = 0;
|
||||
for (uint32_t index_minor : subaddr_indices)
|
||||
|
@ -9720,7 +9752,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
const size_t tx_weight_two_rings = estimate_tx_weight(use_rct, 2, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus);
|
||||
THROW_WALLET_EXCEPTION_IF(tx_weight_one_ring > tx_weight_two_rings, error::wallet_internal_error, "Estimated tx weight with 1 input is larger than with 2 inputs!");
|
||||
const size_t tx_weight_per_ring = tx_weight_two_rings - tx_weight_one_ring;
|
||||
const uint64_t fractional_threshold = (fee_multiplier * base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024);
|
||||
const uint64_t fractional_threshold = (base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024);
|
||||
|
||||
// gather all dust and non-dust outputs belonging to specified subaddresses
|
||||
size_t num_nondust_outputs = 0;
|
||||
|
@ -9814,7 +9846,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
{
|
||||
// this is used to build a tx that's 1 or 2 inputs, and 2 outputs, which
|
||||
// will get us a known fee.
|
||||
uint64_t estimated_fee = estimate_fee(use_per_byte_fee, use_rct, 2, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus, base_fee, fee_multiplier, fee_quantization_mask);
|
||||
uint64_t estimated_fee = estimate_fee(use_per_byte_fee, use_rct, 2, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus, base_fee, fee_quantization_mask);
|
||||
preferred_inputs = pick_preferred_rct_inputs(needed_money + estimated_fee, subaddr_account, subaddr_indices);
|
||||
if (!preferred_inputs.empty())
|
||||
{
|
||||
|
@ -9994,7 +10026,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
pending_tx test_ptx;
|
||||
|
||||
const size_t num_outputs = get_num_outputs(tx.dsts, m_transfers, tx.selected_transfers);
|
||||
needed_fee = estimate_fee(use_per_byte_fee, use_rct ,tx.selected_transfers.size(), fake_outs_count, num_outputs, extra.size(), bulletproof, clsag, bulletproof_plus, base_fee, fee_multiplier, fee_quantization_mask);
|
||||
needed_fee = estimate_fee(use_per_byte_fee, use_rct ,tx.selected_transfers.size(), fake_outs_count, num_outputs, extra.size(), bulletproof, clsag, bulletproof_plus, base_fee, fee_quantization_mask);
|
||||
|
||||
auto try_carving_from_partial_payment = [&](uint64_t needed_fee, uint64_t available_for_fee)
|
||||
{
|
||||
|
@ -10048,7 +10080,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
|
||||
auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
|
||||
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask);
|
||||
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_quantization_mask);
|
||||
available_for_fee = test_ptx.fee + test_ptx.change_dts.amount + (!test_ptx.dust_added_to_fee ? test_ptx.dust : 0);
|
||||
LOG_PRINT_L2("Made a " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_money(available_for_fee) << " available for fee (" <<
|
||||
print_money(needed_fee) << " needed)");
|
||||
|
@ -10073,7 +10105,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
|
||||
txBlob = t_serializable_object_to_blob(test_ptx.tx);
|
||||
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask);
|
||||
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_quantization_mask);
|
||||
LOG_PRINT_L2("Made an attempt at a final " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_money(test_ptx.fee) <<
|
||||
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
|
||||
}
|
||||
|
@ -10256,13 +10288,12 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
|
|||
const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
|
||||
const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0);
|
||||
const bool clsag = use_fork_rules(get_clsag_fork(), 0);
|
||||
const uint64_t base_fee = get_base_fee();
|
||||
const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm());
|
||||
const uint64_t base_fee = get_base_fee(priority);
|
||||
const size_t tx_weight_one_ring = estimate_tx_weight(use_rct, 1, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus);
|
||||
const size_t tx_weight_two_rings = estimate_tx_weight(use_rct, 2, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus);
|
||||
THROW_WALLET_EXCEPTION_IF(tx_weight_one_ring > tx_weight_two_rings, error::wallet_internal_error, "Estimated tx weight with 1 input is larger than with 2 inputs!");
|
||||
const size_t tx_weight_per_ring = tx_weight_two_rings - tx_weight_one_ring;
|
||||
const uint64_t fractional_threshold = (fee_multiplier * base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024);
|
||||
const uint64_t fractional_threshold = (base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024);
|
||||
|
||||
THROW_WALLET_EXCEPTION_IF(unlocked_balance(subaddr_account, false) == 0, error::wallet_internal_error, "No unlocked balance in the specified account");
|
||||
|
||||
|
@ -10371,8 +10402,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||
rct::RangeProofPaddedBulletproof,
|
||||
bulletproof_plus ? 4 : 3
|
||||
};
|
||||
const uint64_t base_fee = get_base_fee();
|
||||
const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm());
|
||||
const uint64_t base_fee = get_base_fee(priority);
|
||||
const uint64_t fee_quantization_mask = get_fee_quantization_mask();
|
||||
|
||||
LOG_PRINT_L2("Starting with " << unused_transfers_indices.size() << " non-dust outputs and " << unused_dust_indices.size() << " dust outputs");
|
||||
|
@ -10399,11 +10429,11 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||
if (use_fork_rules(HF_VERSION_PER_BYTE_FEE))
|
||||
{
|
||||
const uint64_t estimated_tx_weight_with_one_extra_output = estimate_tx_weight(use_rct, tx.selected_transfers.size() + 1, fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag, bulletproof_plus);
|
||||
fee_dust_threshold = calculate_fee_from_weight(base_fee, estimated_tx_weight_with_one_extra_output, fee_multiplier, fee_quantization_mask);
|
||||
fee_dust_threshold = calculate_fee_from_weight(base_fee, estimated_tx_weight_with_one_extra_output, fee_quantization_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
fee_dust_threshold = base_fee * fee_multiplier * (upper_transaction_weight_limit + 1023) / 1024;
|
||||
fee_dust_threshold = base_fee * (upper_transaction_weight_limit + 1023) / 1024;
|
||||
}
|
||||
|
||||
size_t idx =
|
||||
|
@ -10437,7 +10467,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||
pending_tx test_ptx;
|
||||
|
||||
const size_t num_outputs = get_num_outputs(tx.dsts, m_transfers, tx.selected_transfers);
|
||||
needed_fee = estimate_fee(use_per_byte_fee, use_rct, tx.selected_transfers.size(), fake_outs_count, num_outputs, extra.size(), bulletproof, clsag, bulletproof_plus, base_fee, fee_multiplier, fee_quantization_mask);
|
||||
needed_fee = estimate_fee(use_per_byte_fee, use_rct, tx.selected_transfers.size(), fake_outs_count, num_outputs, extra.size(), bulletproof, clsag, bulletproof_plus, base_fee, fee_quantization_mask);
|
||||
|
||||
// add N - 1 outputs for correct initial fee estimation
|
||||
for (size_t i = 0; i < ((outputs > 1) ? outputs - 1 : outputs); ++i)
|
||||
|
@ -10452,7 +10482,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
|
||||
auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
|
||||
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask);
|
||||
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_quantization_mask);
|
||||
available_for_fee = test_ptx.fee + test_ptx.change_dts.amount;
|
||||
for (auto &dt: test_ptx.dests)
|
||||
available_for_fee += dt.amount;
|
||||
|
@ -10489,7 +10519,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
|
||||
txBlob = t_serializable_object_to_blob(test_ptx.tx);
|
||||
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask);
|
||||
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_quantization_mask);
|
||||
LOG_PRINT_L2("Made an attempt at a final " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_money(test_ptx.fee) <<
|
||||
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
|
||||
} while (needed_fee > test_ptx.fee);
|
||||
|
@ -10816,7 +10846,7 @@ std::vector<wallet2::pending_tx> wallet2::create_unmixable_sweep_transactions()
|
|||
const bool hf1_rules = use_fork_rules(2, 10); // first hard fork has version 2
|
||||
tx_dust_policy dust_policy(hf1_rules ? 0 : ::config::DEFAULT_DUST_THRESHOLD);
|
||||
|
||||
const uint64_t base_fee = get_base_fee();
|
||||
const uint64_t base_fee = get_base_fee(1);
|
||||
|
||||
// may throw
|
||||
std::vector<size_t> unmixable_outputs = select_available_unmixable_outputs();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue