diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 2d01b2bb2..a7cf5cff7 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -29,6 +29,7 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include +#include #include #include #include @@ -42,6 +43,7 @@ #include "blockchain_db/blockchain_db.h" #include "int-util.h" #include "misc_language.h" +#include "misc_log_ex.h" #include "warnings.h" #include "common/perf_timer.h" #include "crypto/hash.h" @@ -464,7 +466,7 @@ namespace cryptonote break; try { - const crypto::hash &txid = it->second; + const crypto::hash &txid = it->get_right(); txpool_tx_meta_t meta; if (!m_blockchain.get_txpool_tx_meta(txid, meta)) { @@ -491,11 +493,11 @@ namespace cryptonote return; } // remove first, in case this throws, so key images aren't removed - MINFO("Pruning tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->first.first); + MINFO("Pruning tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->get_left().first); m_blockchain.remove_txpool_tx(txid); reduce_txpool_weight(meta.weight); remove_transaction_keyimages(tx, txid); - MINFO("Pruned tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->first.first); + MINFO("Pruned tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->get_left().first); auto it_prev = it; --it_prev; @@ -751,13 +753,9 @@ namespace cryptonote m_remove_stuck_tx_interval.do_call([this](){return remove_stuck_transactions();}); } //--------------------------------------------------------------------------------- - 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) { - 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){ - return a.second == id; - } - ); + return m_txs_by_fee_and_receive_time.project_up(m_txs_by_fee_and_receive_time.right.find(id)); } //--------------------------------------------------------------------------------- //TODO: investigate whether boolean return is appropriate @@ -1644,15 +1642,15 @@ namespace cryptonote for (; sorted_it != m_txs_by_fee_and_receive_time.end(); ++sorted_it) { txpool_tx_meta_t meta; - if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta)) + if (!m_blockchain.get_txpool_tx_meta(sorted_it->get_right(), meta)) { static bool warned = false; if (!warned) - MERROR(" failed to find tx meta: " << sorted_it->second << " (will only print once)"); + MERROR(" failed to find tx meta: " << sorted_it->get_right() << " (will only print once)"); warned = true; continue; } - LOG_PRINT_L2("Considering " << sorted_it->second << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_money(best_coinbase) << ", relay method " << (unsigned)meta.get_relay_method()); + LOG_PRINT_L2("Considering " << sorted_it->get_right() << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_money(best_coinbase) << ", relay method " << (unsigned)meta.get_relay_method()); if (!meta.matches(relay_category::legacy) && !(m_mine_stem_txes && meta.get_relay_method() == relay_method::stem)) { @@ -1702,7 +1700,7 @@ namespace cryptonote } // "local" and "stem" txes are filtered above - cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(sorted_it->second, relay_category::all); + cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(sorted_it->get_right(), relay_category::all); cryptonote::transaction tx; @@ -1713,7 +1711,7 @@ namespace cryptonote bool ready = false; try { - ready = is_transaction_ready_to_go(meta, sorted_it->second, txblob, tx); + ready = is_transaction_ready_to_go(meta, sorted_it->get_right(), txblob, tx); } catch (const std::exception &e) { @@ -1724,7 +1722,7 @@ namespace cryptonote { try { - m_blockchain.update_txpool_tx(sorted_it->second, meta); + m_blockchain.update_txpool_tx(sorted_it->get_right(), meta); } catch (const std::exception &e) { @@ -1743,7 +1741,7 @@ namespace cryptonote continue; } - bl.tx_hashes.push_back(sorted_it->second); + bl.tx_hashes.push_back(sorted_it->get_right()); total_weight += meta.weight; fee += meta.fee; best_coinbase = coinbase; @@ -1854,7 +1852,11 @@ namespace cryptonote m_txs_by_fee_and_receive_time.erase(sorted_it); } } - m_txs_by_fee_and_receive_time.emplace(std::pair(fee, receive_time), txid); + auto insert_result = m_txs_by_fee_and_receive_time.insert(sorted_tx_container::value_type(std::pair(fee, receive_time), txid)); + + if (!insert_result.second) { + MERROR("Failed to add txid " << txid << " to the m_txs_by_fee_and_receive_time"); + } // Don't check for "resurrected" txs in case of reorgs i.e. don't check in 'm_removed_txs_by_time' // whether we have that txid there and if yes remove it; this results in possible duplicates diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 69a123fc9..a77f3b3f5 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -39,6 +39,9 @@ #include #include #include +#include +#include +#include #include "span.h" #include "string_tools.h" @@ -62,24 +65,33 @@ namespace cryptonote //! pair of for organization typedef std::pair, crypto::hash> tx_by_fee_and_receive_time_entry; - class txCompare + class txFeeCompare { public: - bool operator()(const tx_by_fee_and_receive_time_entry& a, const tx_by_fee_and_receive_time_entry& b) const + bool operator()(const std::pair& a, const std::pair& b) const { // sort by greatest first, not least - if (a.first.first > b.first.first) return true; - if (a.first.first < b.first.first) return false; + if (a.first > b.first) return true; + if (a.first < b.first) return false; - if (a.first.second < b.first.second) return true; - if (a.first.second > b.first.second) return false; + if (a.second < b.second) return true; + return false; + } + }; - return memcmp(a.second.data, b.second.data, sizeof(crypto::hash)) < 0; + class hashCompare + { + public: + bool operator()(const crypto::hash& a, const crypto::hash& b) const + { + return memcmp(a.data, b.data, sizeof(crypto::hash)) < 0; } }; //! container for sorting transactions by fee per unit size - typedef std::set sorted_tx_container; + typedef boost::bimap, txFeeCompare>, + boost::bimaps::set_of> sorted_tx_container; + /** * @brief Transaction pool, handles transactions which are not part of a block @@ -653,7 +665,7 @@ private: * * @return an iterator, possibly to the end of the container if not found */ - sorted_tx_container::iterator find_tx_in_sorted_container(const crypto::hash& id) const; + sorted_tx_container::iterator find_tx_in_sorted_container(const crypto::hash& id); //! cache/call Blockchain::check_tx_inputs results bool check_tx_inputs(const std::function &get_tx, const crypto::hash &txid, uint64_t &max_used_block_height, crypto::hash &max_used_block_id, tx_verification_context &tvc, bool kept_by_block = false) const;