mirror of
https://github.com/monero-project/monero.git
synced 2026-06-12 19:11:36 -07:00
wallet: Improve Fee Priority Code for Clarity
This commit is contained in:
+65
-52
@@ -40,6 +40,7 @@
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/archive/binary_iarchive.hpp>
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
@@ -1198,7 +1199,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
|
||||
m_print_ring_members(false),
|
||||
m_store_tx_info(true),
|
||||
m_default_mixin(0),
|
||||
m_default_priority(0),
|
||||
m_default_priority(fee_priority::Default),
|
||||
m_refresh_type(RefreshOptimizeCoinbase),
|
||||
m_auto_refresh(true),
|
||||
m_first_refresh_done(false),
|
||||
@@ -4606,7 +4607,7 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const crypt
|
||||
value2.SetUint(m_default_mixin);
|
||||
json.AddMember("default_mixin", value2, json.GetAllocator());
|
||||
|
||||
value2.SetUint(m_default_priority);
|
||||
value2.SetUint(boost::numeric_cast<unsigned>(fee_priority_utilities::as_integral(m_default_priority)));
|
||||
json.AddMember("default_priority", value2, json.GetAllocator());
|
||||
|
||||
value2.SetInt(m_auto_refresh ? 1 :0);
|
||||
@@ -4938,7 +4939,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
|
||||
m_print_ring_members = false;
|
||||
m_store_tx_info = true;
|
||||
m_default_mixin = 0;
|
||||
m_default_priority = 0;
|
||||
m_default_priority = fee_priority::Default;
|
||||
m_auto_refresh = true;
|
||||
m_refresh_type = RefreshType::RefreshDefault;
|
||||
m_refresh_from_block_height = 0;
|
||||
@@ -5071,15 +5072,15 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
|
||||
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, default_priority, unsigned int, Uint, false, 0);
|
||||
if (field_default_priority_found)
|
||||
{
|
||||
m_default_priority = field_default_priority;
|
||||
m_default_priority = fee_priority_utilities::from_integral(boost::numeric_cast<uint32_t>(field_default_priority));
|
||||
}
|
||||
else
|
||||
{
|
||||
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, default_fee_multiplier, unsigned int, Uint, false, 0);
|
||||
if (field_default_fee_multiplier_found)
|
||||
m_default_priority = field_default_fee_multiplier;
|
||||
m_default_priority = fee_priority_utilities::from_integral(boost::numeric_cast<uint32_t>(field_default_fee_multiplier));
|
||||
else
|
||||
m_default_priority = 0;
|
||||
m_default_priority = fee_priority::Default;
|
||||
}
|
||||
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, auto_refresh, int, Int, false, true);
|
||||
m_auto_refresh = field_auto_refresh;
|
||||
@@ -8470,42 +8471,45 @@ uint64_t wallet2::estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t wallet2::get_fee_multiplier(uint32_t priority, int fee_algorithm)
|
||||
uint64_t wallet2::get_fee_multiplier(fee_priority priority, fee_algorithm fee_algorithm)
|
||||
{
|
||||
static const struct
|
||||
struct fee_step
|
||||
{
|
||||
size_t count;
|
||||
uint64_t multipliers[4];
|
||||
}
|
||||
multipliers[] =
|
||||
{
|
||||
{ 3, {1, 2, 3} },
|
||||
{ 3, {1, 20, 166} },
|
||||
{ 4, {1, 4, 20, 166} },
|
||||
{ 4, {1, 5, 25, 1000} },
|
||||
fee_priority maximum_priority; // Determines the maximum priority available for said fee algorithm.
|
||||
uint64_t fee_multipliers[4]; // Determines the fee multiplier applied at various priorities for said fee algorithm.
|
||||
};
|
||||
|
||||
if (fee_algorithm == -1)
|
||||
static constexpr fee_step fee_steps[] =
|
||||
{
|
||||
{ fee_priority::Elevated, {1, 2, 3} },
|
||||
{ fee_priority::Elevated, {1, 20, 166} },
|
||||
{ fee_priority::Priority, {1, 4, 20, 166} },
|
||||
{ fee_priority::Priority, {1, 5, 25, 1000} },
|
||||
};
|
||||
|
||||
if (fee_algorithm == fee_algorithm::Unset)
|
||||
fee_algorithm = get_fee_algorithm();
|
||||
|
||||
// 0 -> default (here, x1 till fee algorithm 2, x4 from it)
|
||||
if (priority == 0)
|
||||
if (priority == fee_priority::Default)
|
||||
priority = m_default_priority;
|
||||
if (priority == 0)
|
||||
if (priority == fee_priority::Default)
|
||||
{
|
||||
if (fee_algorithm >= 2)
|
||||
priority = 2;
|
||||
if (fee_algorithm >= fee_algorithm::HardforkV5)
|
||||
priority = fee_priority::Normal;
|
||||
else
|
||||
priority = 1;
|
||||
priority = fee_priority::Unimportant;
|
||||
}
|
||||
|
||||
THROW_WALLET_EXCEPTION_IF(fee_algorithm < 0 || fee_algorithm > 3, error::invalid_priority);
|
||||
const auto fee_algorithm_index = fee_algorithm_utilities::as_integral(fee_algorithm);
|
||||
THROW_WALLET_EXCEPTION_IF(fee_algorithm_index < 0 || fee_algorithm_index > static_cast<int>(std::size(fee_steps)), error::invalid_priority);
|
||||
|
||||
// 1 to 3/4 are allowed as priorities
|
||||
const uint32_t max_priority = multipliers[fee_algorithm].count;
|
||||
if (priority >= 1 && priority <= max_priority)
|
||||
const fee_priority max_priority = fee_steps[fee_algorithm_index].maximum_priority;
|
||||
if (priority >= fee_priority::Unimportant && priority <= max_priority)
|
||||
{
|
||||
return multipliers[fee_algorithm].multipliers[priority-1];
|
||||
const fee_priority adjusted_priority = fee_priority_utilities::decrease(priority);
|
||||
return fee_steps[fee_algorithm_index].fee_multipliers[fee_priority_utilities::as_integral(adjusted_priority)];
|
||||
}
|
||||
|
||||
THROW_WALLET_EXCEPTION_IF (false, error::invalid_priority);
|
||||
@@ -8533,16 +8537,18 @@ uint64_t wallet2::get_base_fee()
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::get_base_fee(uint32_t priority)
|
||||
{
|
||||
return get_base_fee(fee_priority_utilities::from_integral(priority));
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::get_base_fee(fee_priority 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;
|
||||
priority = fee_priority_utilities::clamp_modified(priority);
|
||||
priority = fee_priority_utilities::decrease(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);
|
||||
@@ -8551,12 +8557,14 @@ uint64_t wallet2::get_base_fee(uint32_t priority)
|
||||
MERROR("Failed to determine base fee, using default");
|
||||
return FEE_PER_BYTE;
|
||||
}
|
||||
if (priority >= fees.size())
|
||||
|
||||
const auto priority_index = fee_priority_utilities::as_integral(priority);
|
||||
if (priority_index >= fees.size())
|
||||
{
|
||||
MERROR("Failed to determine base fee for priority " << priority << ", using default");
|
||||
MERROR("Failed to determine base fee for priority " << priority_index << ", using default");
|
||||
return FEE_PER_BYTE;
|
||||
}
|
||||
return fees[priority];
|
||||
return fees[priority_index];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -8579,16 +8587,16 @@ uint64_t wallet2::get_fee_quantization_mask()
|
||||
return fee_quantization_mask;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
int wallet2::get_fee_algorithm()
|
||||
fee_algorithm wallet2::get_fee_algorithm()
|
||||
{
|
||||
// changes at v3, v5, v8
|
||||
if (use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0))
|
||||
return 3;
|
||||
return fee_algorithm::HardforkV8;
|
||||
if (use_fork_rules(5, 0))
|
||||
return 2;
|
||||
return fee_algorithm::HardforkV5;
|
||||
if (use_fork_rules(3, -30 * 14))
|
||||
return 1;
|
||||
return 0;
|
||||
return fee_algorithm::HardforkV3;
|
||||
return fee_algorithm::PreHardforkV3;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::get_min_ring_size()
|
||||
@@ -8632,15 +8640,20 @@ uint64_t wallet2::adjust_mixin(uint64_t mixin)
|
||||
return mixin;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint32_t wallet2::adjust_priority(uint32_t priority)
|
||||
fee_priority wallet2::adjust_priority(uint32_t priority)
|
||||
{
|
||||
if (priority == 0 && m_default_priority == 0 && auto_low_priority())
|
||||
return adjust_priority(fee_priority_utilities::from_integral(priority));
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
fee_priority wallet2::adjust_priority(fee_priority priority)
|
||||
{
|
||||
if (priority == fee_priority::Default && m_default_priority == fee_priority::Default && auto_low_priority())
|
||||
{
|
||||
try
|
||||
{
|
||||
// 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(1);
|
||||
const uint64_t base_fee = get_base_fee(fee_priority::Unimportant);
|
||||
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)
|
||||
@@ -8651,7 +8664,7 @@ uint32_t wallet2::adjust_priority(uint32_t priority)
|
||||
else if (blocks[0].first > 0)
|
||||
{
|
||||
MINFO("We don't use the low priority because there's a backlog in the tx pool.");
|
||||
return 2;
|
||||
return fee_priority::Normal;
|
||||
}
|
||||
|
||||
// get the current full reward zone
|
||||
@@ -8696,10 +8709,10 @@ uint32_t wallet2::adjust_priority(uint32_t priority)
|
||||
if (P > 80)
|
||||
{
|
||||
MINFO("We don't use the low priority because recent blocks are quite full.");
|
||||
return 2;
|
||||
return fee_priority::Normal;
|
||||
}
|
||||
MINFO("We'll use the low priority because probably it's safe to do so.");
|
||||
return 1;
|
||||
return fee_priority::Unimportant;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -10420,7 +10433,7 @@ static uint32_t get_count_above(const std::vector<wallet2::transfer_details> &tr
|
||||
// This system allows for sending (almost) the entire balance, since it does
|
||||
// not generate spurious change in all txes, thus decreasing the instantaneous
|
||||
// usable balance.
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const unique_index_container& subtract_fee_from_outputs)
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, fee_priority priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const unique_index_container& subtract_fee_from_outputs)
|
||||
{
|
||||
//ensure device is let in NONE mode in any case
|
||||
hw::device &hwdev = m_account.get_device();
|
||||
@@ -11188,7 +11201,7 @@ bool wallet2::sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, c
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices)
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, fee_priority priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices)
|
||||
{
|
||||
std::vector<size_t> unused_transfers_indices;
|
||||
std::vector<size_t> unused_dust_indices;
|
||||
@@ -11261,7 +11274,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
|
||||
return create_transactions_from(address, is_subaddress, outputs, unused_transfers_indices, unused_dust_indices, fake_outs_count, priority, extra);
|
||||
}
|
||||
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra)
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, fee_priority priority, const std::vector<uint8_t>& extra)
|
||||
{
|
||||
std::vector<size_t> unused_transfers_indices;
|
||||
std::vector<size_t> unused_dust_indices;
|
||||
@@ -11282,7 +11295,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt
|
||||
return create_transactions_from(address, is_subaddress, outputs, unused_transfers_indices, unused_dust_indices, fake_outs_count, priority, extra);
|
||||
}
|
||||
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra)
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, fee_priority priority, const std::vector<uint8_t>& extra)
|
||||
{
|
||||
//ensure device is let in NONE mode in any case
|
||||
hw::device &hwdev = m_account.get_device();
|
||||
@@ -11751,7 +11764,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(1);
|
||||
const uint64_t base_fee = get_base_fee(fee_priority::Unimportant);
|
||||
|
||||
// may throw
|
||||
std::vector<size_t> unmixable_outputs = select_available_unmixable_outputs();
|
||||
@@ -11772,7 +11785,7 @@ std::vector<wallet2::pending_tx> wallet2::create_unmixable_sweep_transactions()
|
||||
unmixable_transfer_outputs.push_back(n);
|
||||
}
|
||||
|
||||
return create_transactions_from(m_account_public_address, false, 1, unmixable_transfer_outputs, unmixable_dust_outputs, 0 /*fake_outs_count */, 1 /*priority */, std::vector<uint8_t>());
|
||||
return create_transactions_from(m_account_public_address, false, 1, unmixable_transfer_outputs, unmixable_dust_outputs, 0 /*fake_outs_count */, fee_priority::Unimportant, std::vector<uint8_t>());
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::discard_unmixable_outputs()
|
||||
|
||||
Reference in New Issue
Block a user