diff options
-rw-r--r-- | src/common/dns_utils.cpp | 34 | ||||
-rw-r--r-- | src/common/dns_utils.h | 5 | ||||
-rw-r--r-- | src/cryptonote_core/tx_pool.cpp | 45 | ||||
-rw-r--r-- | src/cryptonote_core/tx_pool.h | 7 |
4 files changed, 65 insertions, 26 deletions
diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index ea7f1078b..347cf758a 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -205,13 +205,15 @@ std::vector<std::string> DNSResolver::get_ipv4(const std::string& url, bool& dns dnssec_valid = false; char urlC[1000]; // waaaay too big, but just in case... - strncpy(urlC, url.c_str(), 999); - urlC[999] = '\0'; - if (!check_address_syntax(urlC)) + std::string url_copy{url}; + if (!check_address_syntax(url_copy)) { return addresses; } + strncpy(urlC, url_copy.c_str(), 999); + urlC[999] = '\0'; + // destructor takes care of cleanup ub_result_ptr result; @@ -239,14 +241,15 @@ std::vector<std::string> DNSResolver::get_ipv6(const std::string& url, bool& dns dnssec_valid = false; char urlC[1000]; // waaaay too big, but just in case... - strncpy(urlC, url.c_str(), 999); - urlC[999] = '\0'; - - if (!check_address_syntax(urlC)) + std::string url_copy{url}; + if (!check_address_syntax(url_copy)) { return addresses; } + strncpy(urlC, url_copy.c_str(), 999); + urlC[999] = '\0'; + ub_result_ptr result; // call DNS resolver, blocking. if return value not zero, something went wrong @@ -273,14 +276,15 @@ std::vector<std::string> DNSResolver::get_txt_record(const std::string& url, boo dnssec_valid = false; char urlC[1000]; // waaaay too big, but just in case... - strncpy(urlC, url.c_str(), 999); - urlC[999] = '\0'; - - if (!check_address_syntax(urlC)) + std::string url_copy{url}; + if (!check_address_syntax(url_copy)) { return records; } + strncpy(urlC, url_copy.c_str(), 999); + urlC[999] = '\0'; + ub_result_ptr result; // call DNS resolver, blocking. if return value not zero, something went wrong @@ -314,13 +318,17 @@ DNSResolver& DNSResolver::instance() return *staticInstance; } -bool DNSResolver::check_address_syntax(const std::string& addr) +bool DNSResolver::check_address_syntax(std::string& addr) { // if string doesn't contain a dot, we won't consider it a url for now. - if (addr.find(".") == std::string::npos) + auto first_dot = addr.find("."); + if (first_dot == std::string::npos) { return false; } + + // allow name@domain.tld to work + addr.replace(first_dot, 1, "@"); return true; } diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h index a16c7eff7..4e48acb09 100644 --- a/src/common/dns_utils.h +++ b/src/common/dns_utils.h @@ -112,11 +112,14 @@ private: /** * @brief Checks a string to see if it looks like a URL * + * If the address looks good, but contains one @ symbol, replace that with a . + * e.g. donate@getmonero.org becomes donate.getmonero.org + * * @param addr the string to be checked * * @return true if it looks enough like a URL, false if not */ - bool check_address_syntax(const std::string& addr); + bool check_address_syntax(std::string& addr); DNSResolverData *m_data; }; // class DNSResolver diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 5543ac64f..781d1af5c 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -186,6 +186,8 @@ namespace cryptonote } tvc.m_verifivation_failed = false; + + m_txs_by_fee.emplace(id, (double)blob_size / fee); //succeed return true; } @@ -232,11 +234,16 @@ namespace cryptonote if(it == m_transactions.end()) return false; + auto sorted_it = m_txs_by_fee.find(id); + if (sorted_it == m_txs_by_fee.end()) + return false; + tx = it->second.tx; blob_size = it->second.blob_size; fee = it->second.fee; remove_transaction_keyimages(it->second.tx); m_transactions.erase(it); + m_txs_by_fee.erase(sorted_it); return true; } //--------------------------------------------------------------------------------- @@ -258,7 +265,9 @@ namespace cryptonote { LOG_PRINT_L1("Tx " << it->first << " removed from tx pool due to outdated, age: " << tx_age ); remove_transaction_keyimages(it->second.tx); + auto sorted_it = m_txs_by_fee.find(it->first); m_transactions.erase(it++); + m_txs_by_fee.erase(sorted_it); }else ++it; } @@ -470,10 +479,13 @@ namespace cryptonote size_t max_total_size = (130 * median_size) / 100 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; std::unordered_set<crypto::key_image> k_images; - BOOST_FOREACH(transactions_container::value_type& tx, m_transactions) + m_txs_by_fee::const_iterator sorted_it = m_txs_by_fee.begin(); + while (sorted_it != m_txs_by_fee.end()) { + m_transactions::const_iterator tx_it = m_transactions.find(sorted_it->first); + // Can not exceed maximum block size - if (max_total_size < total_size + tx.second.blob_size) + if (max_total_size < total_size + tx_it->second->blob_size) continue; // If adding this tx will make the block size @@ -481,7 +493,7 @@ namespace cryptonote // _BLOCK_SIZE bytes, reject the tx; this will // keep block sizes from becoming too unwieldly // to propagate at 60s block times. - if ( (total_size + tx.second.blob_size) > CRYPTONOTE_GETBLOCKTEMPLATE_MAX_BLOCK_SIZE ) + if ( (total_size + tx_it->second.blob_size) > CRYPTONOTE_GETBLOCKTEMPLATE_MAX_BLOCK_SIZE ) continue; // If we've exceeded the penalty free size, @@ -495,10 +507,11 @@ namespace cryptonote if (!is_transaction_ready_to_go(tx.second) || have_key_images(k_images, tx.second.tx)) continue; - bl.tx_hashes.push_back(tx.first); - total_size += tx.second.blob_size; - fee += tx.second.fee; - append_key_images(k_images, tx.second.tx); + bl.tx_hashes.push_back(tx_it->first); + total_size += tx_it->second.blob_size; + fee += tx_it->second.fee; + append_key_images(k_images, tx_it->second.tx); + sorted_it++; } return true; @@ -523,12 +536,20 @@ namespace cryptonote } for (auto it = m_transactions.begin(); it != m_transactions.end(); ) { - auto it2 = it++; - if (it2->second.blob_size >= TRANSACTION_SIZE_LIMIT) { - LOG_PRINT_L1("Transaction " << get_transaction_hash(it2->second.tx) << " is too big (" << it2->second.blob_size << " bytes), removing it from pool"); - remove_transaction_keyimages(it2->second.tx); - m_transactions.erase(it2); + if (it->second.blob_size >= TRANSACTION_SIZE_LIMIT) { + 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); + auto sorted_it = m_txs_by_fee.find(it->first); + m_txs_by_fee.erase(sorted_it); + m_transactions.erase(it); } + it++; + } + + // no need to store queue of sorted transactions, as it's easy to generate. + for (const auto& tx : m_transactions) + { + m_txs_by_fee.emplace(tx.first, (double)tx.second.blob_size / tx.second.fee); } // Ignore deserialization error diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 77f2e3483..7c8f4a449 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -34,6 +34,7 @@ #include <set> #include <unordered_map> #include <unordered_set> +#include <queue> #include <boost/serialization/version.hpp> #include <boost/utility.hpp> @@ -133,6 +134,12 @@ namespace cryptonote key_images_container m_spent_key_images; epee::math_helper::once_a_time_seconds<30> m_remove_stuck_tx_interval; + typedef std::unordered_map<crypto::hash, double> tx_by_fee_entry; + + //TODO: add fee_per_kb element to type tx_details and replace this + //functionality by just making m_transactions a std::set + std::set<tx_by_fee_entry> m_txs_by_fee; + //transactions_container m_alternative_transactions; std::string m_config_folder; |