simplewallet: new "fee" command to display fee information
including expected transaction backlog at different priorities
This commit is contained in:
parent
d8f402ad8f
commit
31b1c6c10d
4 changed files with 110 additions and 30 deletions
|
@ -391,6 +391,61 @@ bool simple_wallet::payment_id(const std::vector<std::string> &args/* = std::vec
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool simple_wallet::print_fee_info(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
|
||||||
|
{
|
||||||
|
if (!try_connect_to_daemon())
|
||||||
|
{
|
||||||
|
fail_msg_writer() << tr("Cannot connect to daemon");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const uint64_t per_kb_fee = m_wallet->get_per_kb_fee();
|
||||||
|
const uint64_t typical_size_kb = 13;
|
||||||
|
message_writer() << (boost::format(tr("Current fee is %s monero per kB")) % print_money(per_kb_fee)).str();
|
||||||
|
|
||||||
|
std::vector<uint64_t> fees;
|
||||||
|
for (uint32_t priority = 1; priority <= 4; ++priority)
|
||||||
|
{
|
||||||
|
uint64_t mult = m_wallet->get_fee_multiplier(priority);
|
||||||
|
fees.push_back(per_kb_fee * typical_size_kb * mult);
|
||||||
|
}
|
||||||
|
std::vector<std::pair<uint64_t, uint64_t>> blocks;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
uint64_t base_size = typical_size_kb * 1024;
|
||||||
|
blocks = m_wallet->estimate_backlog(base_size, base_size + 1023, fees);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
fail_msg_writer() << tr("Error: failed to estimate backlog array size: ") << e.what();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (blocks.size() != 4)
|
||||||
|
{
|
||||||
|
fail_msg_writer() << tr("Error: bad estimated backlog array size");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t priority = 1; priority <= 4; ++priority)
|
||||||
|
{
|
||||||
|
uint64_t nblocks_low = blocks[priority - 1].first;
|
||||||
|
uint64_t nblocks_high = blocks[priority - 1].second;
|
||||||
|
if (nblocks_low > 0)
|
||||||
|
{
|
||||||
|
std::string msg;
|
||||||
|
if (priority == m_wallet->get_default_priority() || (m_wallet->get_default_priority() == 0 && priority == 2))
|
||||||
|
msg = tr(" (current)");
|
||||||
|
uint64_t minutes_low = nblocks_low * DIFFICULTY_TARGET_V2 / 60, minutes_high = nblocks_high * DIFFICULTY_TARGET_V2 / 60;
|
||||||
|
if (nblocks_high == nblocks_low)
|
||||||
|
message_writer() << (boost::format(tr("%u block (%u minutes) backlog at priority %u%s")) % nblocks_low % minutes_low % priority % msg).str();
|
||||||
|
else
|
||||||
|
message_writer() << (boost::format(tr("%u to %u block (%u to %u minutes) backlog at priority %u")) % nblocks_low % nblocks_high % minutes_low % minutes_high % priority).str();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
message_writer() << tr("No backlog at priority ") << priority;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool simple_wallet::set_always_confirm_transfers(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
|
bool simple_wallet::set_always_confirm_transfers(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
|
||||||
{
|
{
|
||||||
const auto pwd_container = get_and_verify_password();
|
const auto pwd_container = get_and_verify_password();
|
||||||
|
@ -722,6 +777,7 @@ simple_wallet::simple_wallet()
|
||||||
m_cmd_binder.set_handler("show_transfer", boost::bind(&simple_wallet::show_transfer, this, _1), tr("Show information about a transfer to/from this address"));
|
m_cmd_binder.set_handler("show_transfer", boost::bind(&simple_wallet::show_transfer, this, _1), tr("Show information about a transfer to/from this address"));
|
||||||
m_cmd_binder.set_handler("password", boost::bind(&simple_wallet::change_password, this, _1), tr("Change wallet password"));
|
m_cmd_binder.set_handler("password", boost::bind(&simple_wallet::change_password, this, _1), tr("Change wallet password"));
|
||||||
m_cmd_binder.set_handler("payment_id", boost::bind(&simple_wallet::payment_id, this, _1), tr("Generate a new random full size payment id - these will be unencrypted on the blockchain, see integrated_address for encrypted short payment ids"));
|
m_cmd_binder.set_handler("payment_id", boost::bind(&simple_wallet::payment_id, this, _1), tr("Generate a new random full size payment id - these will be unencrypted on the blockchain, see integrated_address for encrypted short payment ids"));
|
||||||
|
m_cmd_binder.set_handler("fee", boost::bind(&simple_wallet::print_fee_info, this, _1), tr("Print information about fee and current transaction backlog"));
|
||||||
m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::help, this, _1), tr("Show this help"));
|
m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::help, this, _1), tr("Show this help"));
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
@ -2461,9 +2517,16 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
uint64_t nblocks = m_wallet->estimate_backlog(size, fee);
|
std::vector<std::pair<uint64_t, uint64_t>> nblocks = m_wallet->estimate_backlog(size, size, {fee});
|
||||||
if (nblocks > 0)
|
if (nblocks.size() != 1)
|
||||||
prompt << (boost::format(tr("There is currently a %u block backlog at that fee level. Is this okay? (Y/Yes/N/No)")) % nblocks).str();
|
{
|
||||||
|
prompt << "Internal error checking for backlog. " << tr("Is this okay anyway? (Y/Yes/N/No): ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (nblocks[0].first > 0)
|
||||||
|
prompt << (boost::format(tr("There is currently a %u block backlog at that fee level. Is this okay? (Y/Yes/N/No)")) % nblocks[0].first).str();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception &e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -175,6 +175,7 @@ namespace cryptonote
|
||||||
bool show_transfer(const std::vector<std::string> &args);
|
bool show_transfer(const std::vector<std::string> &args);
|
||||||
bool change_password(const std::vector<std::string>& args);
|
bool change_password(const std::vector<std::string>& args);
|
||||||
bool payment_id(const std::vector<std::string> &args);
|
bool payment_id(const std::vector<std::string> &args);
|
||||||
|
bool print_fee_info(const std::vector<std::string> &args);
|
||||||
|
|
||||||
uint64_t get_daemon_blockchain_height(std::string& err);
|
uint64_t get_daemon_blockchain_height(std::string& err);
|
||||||
bool try_connect_to_daemon(bool silent = false, uint32_t* version = nullptr);
|
bool try_connect_to_daemon(bool silent = false, uint32_t* version = nullptr);
|
||||||
|
|
|
@ -3457,12 +3457,15 @@ bool wallet2::load_tx(const std::string &signed_filename, std::vector<tools::wal
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
uint64_t wallet2::get_fee_multiplier(uint32_t priority, int fee_algorithm) const
|
uint64_t wallet2::get_fee_multiplier(uint32_t priority, int fee_algorithm)
|
||||||
{
|
{
|
||||||
static const uint64_t old_multipliers[3] = {1, 2, 3};
|
static const uint64_t old_multipliers[3] = {1, 2, 3};
|
||||||
static const uint64_t new_multipliers[3] = {1, 20, 166};
|
static const uint64_t new_multipliers[3] = {1, 20, 166};
|
||||||
static const uint64_t newer_multipliers[4] = {1, 4, 20, 166};
|
static const uint64_t newer_multipliers[4] = {1, 4, 20, 166};
|
||||||
|
|
||||||
|
if (fee_algorithm == -1)
|
||||||
|
fee_algorithm = get_fee_algorithm();
|
||||||
|
|
||||||
// 0 -> default (here, x1 till fee algorithm 2, x4 from it)
|
// 0 -> default (here, x1 till fee algorithm 2, x4 from it)
|
||||||
if (priority == 0)
|
if (priority == 0)
|
||||||
priority = m_default_priority;
|
priority = m_default_priority;
|
||||||
|
@ -5747,10 +5750,14 @@ bool wallet2::is_synced() const
|
||||||
return get_blockchain_current_height() >= height;
|
return get_blockchain_current_height() >= height;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
uint64_t wallet2::estimate_backlog(uint64_t blob_size, uint64_t fee)
|
std::vector<std::pair<uint64_t, uint64_t>> wallet2::estimate_backlog(uint64_t min_blob_size, uint64_t max_blob_size, const std::vector<uint64_t> &fees)
|
||||||
|
{
|
||||||
|
THROW_WALLET_EXCEPTION_IF(min_blob_size == 0, error::wallet_internal_error, "Invalid 0 fee");
|
||||||
|
THROW_WALLET_EXCEPTION_IF(max_blob_size == 0, error::wallet_internal_error, "Invalid 0 fee");
|
||||||
|
for (uint64_t fee: fees)
|
||||||
{
|
{
|
||||||
THROW_WALLET_EXCEPTION_IF(blob_size == 0, error::wallet_internal_error, "Invalid 0 fee");
|
|
||||||
THROW_WALLET_EXCEPTION_IF(fee == 0, error::wallet_internal_error, "Invalid 0 fee");
|
THROW_WALLET_EXCEPTION_IF(fee == 0, error::wallet_internal_error, "Invalid 0 fee");
|
||||||
|
}
|
||||||
|
|
||||||
// get txpool backlog
|
// get txpool backlog
|
||||||
epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG::request> req = AUTO_VAL_INIT(req);
|
epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG::request> req = AUTO_VAL_INIT(req);
|
||||||
|
@ -5776,9 +5783,13 @@ uint64_t wallet2::estimate_backlog(uint64_t blob_size, uint64_t fee)
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_info");
|
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_info");
|
||||||
THROW_WALLET_EXCEPTION_IF(resp_t.result.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_info");
|
THROW_WALLET_EXCEPTION_IF(resp_t.result.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_info");
|
||||||
THROW_WALLET_EXCEPTION_IF(resp_t.result.status != CORE_RPC_STATUS_OK, error::get_tx_pool_error);
|
THROW_WALLET_EXCEPTION_IF(resp_t.result.status != CORE_RPC_STATUS_OK, error::get_tx_pool_error);
|
||||||
|
uint64_t full_reward_zone = resp_t.result.block_size_limit / 2;
|
||||||
|
|
||||||
double our_fee_byte = fee / (double)blob_size;
|
std::vector<std::pair<uint64_t, uint64_t>> blocks;
|
||||||
uint64_t priority_size = 0;
|
for (uint64_t fee: fees)
|
||||||
|
{
|
||||||
|
double our_fee_byte_min = fee / (double)min_blob_size, our_fee_byte_max = fee / (double)max_blob_size;
|
||||||
|
uint64_t priority_size_min = 0, priority_size_max = 0;
|
||||||
for (const auto &i: res.result.backlog)
|
for (const auto &i: res.result.backlog)
|
||||||
{
|
{
|
||||||
if (i.blob_size == 0)
|
if (i.blob_size == 0)
|
||||||
|
@ -5787,16 +5798,20 @@ uint64_t wallet2::estimate_backlog(uint64_t blob_size, uint64_t fee)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
double this_fee_byte = i.fee / (double)i.blob_size;
|
double this_fee_byte = i.fee / (double)i.blob_size;
|
||||||
if (this_fee_byte < our_fee_byte)
|
if (this_fee_byte >= our_fee_byte_min)
|
||||||
continue;
|
priority_size_min += i.blob_size;
|
||||||
priority_size += i.blob_size;
|
if (this_fee_byte >= our_fee_byte_max)
|
||||||
|
priority_size_max += i.blob_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t full_reward_zone = resp_t.result.block_size_limit / 2;
|
uint64_t nblocks_min = (priority_size_min + full_reward_zone - 1) / full_reward_zone;
|
||||||
uint64_t nblocks = (priority_size + full_reward_zone - 1) / full_reward_zone;
|
uint64_t nblocks_max = (priority_size_max + full_reward_zone - 1) / full_reward_zone;
|
||||||
MDEBUG("estimate_backlog: priority_size " << priority_size << " for " << our_fee_byte << " (" << our_fee_byte << " piconero fee/byte), "
|
MDEBUG("estimate_backlog: priority_size " << priority_size_min << " - " << priority_size_max << " for " << fee
|
||||||
<< nblocks << " blocks at block size " << full_reward_zone);
|
<< " (" << our_fee_byte_min << " - " << our_fee_byte_max << " piconero byte fee), "
|
||||||
return nblocks;
|
<< nblocks_min << " - " << nblocks_max << " blocks at block size " << full_reward_zone);
|
||||||
|
blocks.push_back(std::make_pair(nblocks_min, nblocks_max));
|
||||||
|
}
|
||||||
|
return blocks;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::generate_genesis(cryptonote::block& b) {
|
void wallet2::generate_genesis(cryptonote::block& b) {
|
||||||
|
|
|
@ -604,7 +604,10 @@ namespace tools
|
||||||
|
|
||||||
bool is_synced() const;
|
bool is_synced() const;
|
||||||
|
|
||||||
uint64_t estimate_backlog(uint64_t blob_size, uint64_t fee);
|
std::vector<std::pair<uint64_t, uint64_t>> estimate_backlog(uint64_t min_blob_size, uint64_t max_blob_size, const std::vector<uint64_t> &fees);
|
||||||
|
|
||||||
|
uint64_t get_fee_multiplier(uint32_t priority, int fee_algorithm = -1);
|
||||||
|
uint64_t get_per_kb_fee();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
|
@ -646,9 +649,7 @@ namespace tools
|
||||||
void parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const;
|
void parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const;
|
||||||
uint64_t get_upper_transaction_size_limit();
|
uint64_t get_upper_transaction_size_limit();
|
||||||
std::vector<uint64_t> get_unspent_amounts_vector();
|
std::vector<uint64_t> get_unspent_amounts_vector();
|
||||||
uint64_t get_fee_multiplier(uint32_t priority, int fee_algorithm) const;
|
|
||||||
uint64_t get_dynamic_per_kb_fee_estimate();
|
uint64_t get_dynamic_per_kb_fee_estimate();
|
||||||
uint64_t get_per_kb_fee();
|
|
||||||
float get_output_relatedness(const transfer_details &td0, const transfer_details &td1) const;
|
float get_output_relatedness(const transfer_details &td0, const transfer_details &td1) const;
|
||||||
std::vector<size_t> pick_preferred_rct_inputs(uint64_t needed_money) const;
|
std::vector<size_t> pick_preferred_rct_inputs(uint64_t needed_money) const;
|
||||||
void set_spent(size_t idx, uint64_t height);
|
void set_spent(size_t idx, uint64_t height);
|
||||||
|
|
Loading…
Reference in a new issue