mirror of
https://github.com/monero-project/monero.git
synced 2024-12-24 20:49:37 +00:00
Prioritize older transactions in the mempool
The transactions are first prioritized by fee and in case the fees are equal by receive_time.
This commit is contained in:
parent
4026e7b7de
commit
36ba311cf4
2 changed files with 26 additions and 21 deletions
|
@ -177,6 +177,8 @@ namespace cryptonote
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t receive_time = time(nullptr);
|
||||||
|
|
||||||
crypto::hash max_used_block_id = null_hash;
|
crypto::hash max_used_block_id = null_hash;
|
||||||
uint64_t max_used_block_height = 0;
|
uint64_t max_used_block_height = 0;
|
||||||
tx_details txd;
|
tx_details txd;
|
||||||
|
@ -198,7 +200,7 @@ namespace cryptonote
|
||||||
txd_p.first->second.last_failed_height = 0;
|
txd_p.first->second.last_failed_height = 0;
|
||||||
txd_p.first->second.last_failed_id = null_hash;
|
txd_p.first->second.last_failed_id = null_hash;
|
||||||
txd_p.first->second.kept_by_block = kept_by_block;
|
txd_p.first->second.kept_by_block = kept_by_block;
|
||||||
txd_p.first->second.receive_time = time(nullptr);
|
txd_p.first->second.receive_time = receive_time;
|
||||||
txd_p.first->second.last_relayed_time = time(NULL);
|
txd_p.first->second.last_relayed_time = time(NULL);
|
||||||
txd_p.first->second.relayed = relayed;
|
txd_p.first->second.relayed = relayed;
|
||||||
tvc.m_verifivation_impossible = true;
|
tvc.m_verifivation_impossible = true;
|
||||||
|
@ -221,7 +223,7 @@ namespace cryptonote
|
||||||
txd_p.first->second.max_used_block_height = max_used_block_height;
|
txd_p.first->second.max_used_block_height = max_used_block_height;
|
||||||
txd_p.first->second.last_failed_height = 0;
|
txd_p.first->second.last_failed_height = 0;
|
||||||
txd_p.first->second.last_failed_id = null_hash;
|
txd_p.first->second.last_failed_id = null_hash;
|
||||||
txd_p.first->second.receive_time = time(nullptr);
|
txd_p.first->second.receive_time = receive_time;
|
||||||
txd_p.first->second.last_relayed_time = time(NULL);
|
txd_p.first->second.last_relayed_time = time(NULL);
|
||||||
txd_p.first->second.relayed = relayed;
|
txd_p.first->second.relayed = relayed;
|
||||||
tvc.m_added_to_pool = true;
|
tvc.m_added_to_pool = true;
|
||||||
|
@ -246,7 +248,7 @@ namespace cryptonote
|
||||||
|
|
||||||
tvc.m_verifivation_failed = false;
|
tvc.m_verifivation_failed = false;
|
||||||
|
|
||||||
m_txs_by_fee.emplace((double)blob_size / fee, id);
|
m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>((double)blob_size / fee, receive_time), id);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -301,7 +303,7 @@ namespace cryptonote
|
||||||
|
|
||||||
auto sorted_it = find_tx_in_sorted_container(id);
|
auto sorted_it = find_tx_in_sorted_container(id);
|
||||||
|
|
||||||
if (sorted_it == m_txs_by_fee.end())
|
if (sorted_it == m_txs_by_fee_and_receive_time.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
tx = it->second.tx;
|
tx = it->second.tx;
|
||||||
|
@ -310,7 +312,7 @@ namespace cryptonote
|
||||||
relayed = it->second.relayed;
|
relayed = it->second.relayed;
|
||||||
remove_transaction_keyimages(it->second.tx);
|
remove_transaction_keyimages(it->second.tx);
|
||||||
m_transactions.erase(it);
|
m_transactions.erase(it);
|
||||||
m_txs_by_fee.erase(sorted_it);
|
m_txs_by_fee_and_receive_time.erase(sorted_it);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
|
@ -321,7 +323,7 @@ namespace cryptonote
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
sorted_tx_container::iterator tx_memory_pool::find_tx_in_sorted_container(const crypto::hash& id) const
|
sorted_tx_container::iterator tx_memory_pool::find_tx_in_sorted_container(const crypto::hash& id) const
|
||||||
{
|
{
|
||||||
return std::find_if( m_txs_by_fee.begin(), m_txs_by_fee.end()
|
return std::find_if( m_txs_by_fee_and_receive_time.begin(), m_txs_by_fee_and_receive_time.end()
|
||||||
, [&](const sorted_tx_container::value_type& a){
|
, [&](const sorted_tx_container::value_type& a){
|
||||||
return a.second == id;
|
return a.second == id;
|
||||||
}
|
}
|
||||||
|
@ -342,13 +344,13 @@ namespace cryptonote
|
||||||
LOG_PRINT_L1("Tx " << it->first << " removed from tx pool due to outdated, age: " << tx_age );
|
LOG_PRINT_L1("Tx " << it->first << " removed from tx pool due to outdated, age: " << tx_age );
|
||||||
remove_transaction_keyimages(it->second.tx);
|
remove_transaction_keyimages(it->second.tx);
|
||||||
auto sorted_it = find_tx_in_sorted_container(it->first);
|
auto sorted_it = find_tx_in_sorted_container(it->first);
|
||||||
if (sorted_it == m_txs_by_fee.end())
|
if (sorted_it == m_txs_by_fee_and_receive_time.end())
|
||||||
{
|
{
|
||||||
LOG_PRINT_L1("Removing tx " << it->first << " from tx pool, but it was not found in the sorted txs container!");
|
LOG_PRINT_L1("Removing tx " << it->first << " from tx pool, but it was not found in the sorted txs container!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_txs_by_fee.erase(sorted_it);
|
m_txs_by_fee_and_receive_time.erase(sorted_it);
|
||||||
}
|
}
|
||||||
m_timed_out_transactions.insert(it->first);
|
m_timed_out_transactions.insert(it->first);
|
||||||
auto pit = it++;
|
auto pit = it++;
|
||||||
|
@ -608,9 +610,9 @@ namespace cryptonote
|
||||||
size_t max_total_size = 2 * median_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
|
size_t max_total_size = 2 * median_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
|
||||||
std::unordered_set<crypto::key_image> k_images;
|
std::unordered_set<crypto::key_image> k_images;
|
||||||
|
|
||||||
LOG_PRINT_L2("Filling block template, median size " << median_size << ", " << m_txs_by_fee.size() << " txes in the pool");
|
LOG_PRINT_L2("Filling block template, median size " << median_size << ", " << m_txs_by_fee_and_receive_time.size() << " txes in the pool");
|
||||||
auto sorted_it = m_txs_by_fee.begin();
|
auto sorted_it = m_txs_by_fee_and_receive_time.begin();
|
||||||
while (sorted_it != m_txs_by_fee.end())
|
while (sorted_it != m_txs_by_fee_and_receive_time.end())
|
||||||
{
|
{
|
||||||
auto tx_it = m_transactions.find(sorted_it->second);
|
auto tx_it = m_transactions.find(sorted_it->second);
|
||||||
LOG_PRINT_L2("Considering " << tx_it->first << ", size " << tx_it->second.blob_size << ", current block size " << total_size << "/" << max_total_size << ", current coinbase " << print_money(best_coinbase));
|
LOG_PRINT_L2("Considering " << tx_it->first << ", size " << tx_it->second.blob_size << ", current block size " << total_size << "/" << max_total_size << ", current coinbase " << print_money(best_coinbase));
|
||||||
|
@ -675,13 +677,13 @@ namespace cryptonote
|
||||||
LOG_PRINT_L1("Transaction " << get_transaction_hash(it->second.tx) << " is too big (" << it->second.blob_size << " bytes), removing it from pool");
|
LOG_PRINT_L1("Transaction " << get_transaction_hash(it->second.tx) << " is too big (" << it->second.blob_size << " bytes), removing it from pool");
|
||||||
remove_transaction_keyimages(it->second.tx);
|
remove_transaction_keyimages(it->second.tx);
|
||||||
auto sorted_it = find_tx_in_sorted_container(it->first);
|
auto sorted_it = find_tx_in_sorted_container(it->first);
|
||||||
if (sorted_it == m_txs_by_fee.end())
|
if (sorted_it == m_txs_by_fee_and_receive_time.end())
|
||||||
{
|
{
|
||||||
LOG_PRINT_L1("Removing tx " << it->first << " from tx pool, but it was not found in the sorted txs container!");
|
LOG_PRINT_L1("Removing tx " << it->first << " from tx pool, but it was not found in the sorted txs container!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_txs_by_fee.erase(sorted_it);
|
m_txs_by_fee_and_receive_time.erase(sorted_it);
|
||||||
}
|
}
|
||||||
auto pit = it++;
|
auto pit = it++;
|
||||||
m_transactions.erase(pit);
|
m_transactions.erase(pit);
|
||||||
|
@ -712,14 +714,14 @@ namespace cryptonote
|
||||||
LOG_ERROR("Failed to load memory pool from file " << state_file_path);
|
LOG_ERROR("Failed to load memory pool from file " << state_file_path);
|
||||||
|
|
||||||
m_transactions.clear();
|
m_transactions.clear();
|
||||||
m_txs_by_fee.clear();
|
m_txs_by_fee_and_receive_time.clear();
|
||||||
m_spent_key_images.clear();
|
m_spent_key_images.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// no need to store queue of sorted transactions, as it's easy to generate.
|
// no need to store queue of sorted transactions, as it's easy to generate.
|
||||||
for (const auto& tx : m_transactions)
|
for (const auto& tx : m_transactions)
|
||||||
{
|
{
|
||||||
m_txs_by_fee.emplace((double)tx.second.blob_size / tx.second.fee, tx.first);
|
m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>((double)tx.second.blob_size / tx.second.fee, tx.second.receive_time), tx.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore deserialization error
|
// Ignore deserialization error
|
||||||
|
|
|
@ -54,23 +54,25 @@ namespace cryptonote
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
//! pair of <transaction fee, transaction hash> for organization
|
//! pair of <transaction fee, transaction hash> for organization
|
||||||
typedef std::pair<double, crypto::hash> tx_by_fee_entry;
|
typedef std::pair<std::pair<double, std::time_t>, crypto::hash> tx_by_fee_and_receive_time_entry;
|
||||||
|
|
||||||
class txCompare
|
class txCompare
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool operator()(const tx_by_fee_entry& a, const tx_by_fee_entry& b)
|
bool operator()(const tx_by_fee_and_receive_time_entry& a, const tx_by_fee_and_receive_time_entry& b)
|
||||||
{
|
{
|
||||||
// sort by greatest first, not least
|
// sort by greatest first, not least
|
||||||
if (a.first > b.first) return true;
|
if (a.first.first > b.first.first) return true;
|
||||||
else if (a.first < b.first) return false;
|
else if (a.first.first < b.first.first) return false;
|
||||||
|
else if (a.first.second < b.first.second) return true;
|
||||||
|
else if (a.first.second > b.first.second) return false;
|
||||||
else if (a.second != b.second) return true;
|
else if (a.second != b.second) return true;
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//! container for sorting transactions by fee per unit size
|
//! container for sorting transactions by fee per unit size
|
||||||
typedef std::set<tx_by_fee_entry, txCompare> sorted_tx_container;
|
typedef std::set<tx_by_fee_and_receive_time_entry, txCompare> sorted_tx_container;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Transaction pool, handles transactions which are not part of a block
|
* @brief Transaction pool, handles transactions which are not part of a block
|
||||||
|
@ -473,7 +475,8 @@ private:
|
||||||
epee::math_helper::once_a_time_seconds<30> m_remove_stuck_tx_interval;
|
epee::math_helper::once_a_time_seconds<30> m_remove_stuck_tx_interval;
|
||||||
|
|
||||||
//TODO: look into doing this better
|
//TODO: look into doing this better
|
||||||
sorted_tx_container m_txs_by_fee; //!< container for transactions organized by fee per size
|
//!< container for transactions organized by fee per size and receive time
|
||||||
|
sorted_tx_container m_txs_by_fee_and_receive_time;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get an iterator to a transaction in the sorted container
|
* @brief get an iterator to a transaction in the sorted container
|
||||||
|
|
Loading…
Reference in a new issue