aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core/tx_pool.cpp
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-01-29 21:20:24 +0000
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-02-07 13:42:12 +0000
commitbc61ae69bfb20d2bdfa3d3716691e316bdbb6cb5 (patch)
tree99d8c5284cfbeda4f957c1c6381a8234cb0efcde /src/cryptonote_core/tx_pool.cpp
parenttxpool: increase unmined tx expiry to three days (diff)
downloadmonero-bc61ae69bfb20d2bdfa3d3716691e316bdbb6cb5.tar.xz
tx_pool: add a max pool size, settable with --max-txpool-size
Diffstat (limited to 'src/cryptonote_core/tx_pool.cpp')
-rw-r--r--src/cryptonote_core/tx_pool.cpp82
1 files changed, 80 insertions, 2 deletions
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index e75584bce..d7d1c25a5 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -102,7 +102,7 @@ namespace cryptonote
}
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
- tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs)
+ tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs), m_txpool_max_size(DEFAULT_TXPOOL_MAX_SIZE), m_txpool_size(0)
{
}
@@ -295,8 +295,12 @@ namespace cryptonote
}
tvc.m_verifivation_failed = false;
+ m_txpool_size += blob_size;
MINFO("Transaction added to pool: txid " << id << " bytes: " << blob_size << " fee/byte: " << (fee / (double)blob_size));
+
+ prune(m_txpool_max_size);
+
return true;
}
//---------------------------------------------------------------------------------
@@ -309,6 +313,72 @@ namespace cryptonote
return add_tx(tx, h, blob_size, tvc, keeped_by_block, relayed, do_not_relay, version);
}
//---------------------------------------------------------------------------------
+ size_t tx_memory_pool::get_txpool_size() const
+ {
+ CRITICAL_REGION_LOCAL(m_transactions_lock);
+ return m_txpool_size;
+ }
+ //---------------------------------------------------------------------------------
+ void tx_memory_pool::set_txpool_max_size(size_t bytes)
+ {
+ CRITICAL_REGION_LOCAL(m_transactions_lock);
+ m_txpool_max_size = bytes;
+ }
+ //---------------------------------------------------------------------------------
+ void tx_memory_pool::prune(size_t bytes)
+ {
+ CRITICAL_REGION_LOCAL(m_transactions_lock);
+ if (bytes == 0)
+ bytes = m_txpool_max_size;
+ CRITICAL_REGION_LOCAL1(m_blockchain);
+ LockedTXN lock(m_blockchain);
+
+ // this will never remove the first one, but we don't care
+ auto it = --m_txs_by_fee_and_receive_time.end();
+ while (it != m_txs_by_fee_and_receive_time.begin())
+ {
+ if (m_txpool_size <= bytes)
+ break;
+ try
+ {
+ const crypto::hash &txid = it->second;
+ txpool_tx_meta_t meta;
+ if (!m_blockchain.get_txpool_tx_meta(txid, meta))
+ {
+ MERROR("Failed to find tx in txpool");
+ return;
+ }
+ // don't prune the kept_by_block ones, they're likely added because we're adding a block with those
+ if (meta.kept_by_block)
+ {
+ --it;
+ continue;
+ }
+ cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid);
+ cryptonote::transaction tx;
+ if (!parse_and_validate_tx_from_blob(txblob, tx))
+ {
+ MERROR("Failed to parse tx from txpool");
+ return;
+ }
+ // remove first, in case this throws, so key images aren't removed
+ MINFO("Pruning tx " << txid << " from txpool: size: " << it->first.second << ", fee/byte: " << it->first.first);
+ m_blockchain.remove_txpool_tx(txid);
+ m_txpool_size -= txblob.size();
+ remove_transaction_keyimages(tx);
+ MINFO("Pruned tx " << txid << " from txpool: size: " << it->first.second << ", fee/byte: " << it->first.first);
+ m_txs_by_fee_and_receive_time.erase(it--);
+ }
+ catch (const std::exception &e)
+ {
+ MERROR("Error while pruning txpool: " << e.what());
+ return;
+ }
+ }
+ if (m_txpool_size > bytes)
+ MINFO("Pool size after pruning is larger than limit: " << m_txpool_size << "/" << bytes);
+ }
+ //---------------------------------------------------------------------------------
bool tx_memory_pool::insert_key_images(const transaction &tx, bool kept_by_block)
{
for(const auto& in: tx.vin)
@@ -391,6 +461,7 @@ namespace cryptonote
// remove first, in case this throws, so key images aren't removed
m_blockchain.remove_txpool_tx(id);
+ m_txpool_size -= blob_size;
remove_transaction_keyimages(tx);
}
catch (const std::exception &e)
@@ -463,6 +534,7 @@ namespace cryptonote
{
// remove first, so we only remove key images if the tx removal succeeds
m_blockchain.remove_txpool_tx(txid);
+ m_txpool_size -= bd.size();
remove_transaction_keyimages(tx);
}
}
@@ -1125,7 +1197,9 @@ namespace cryptonote
size_t tx_size_limit = get_transaction_size_limit(version);
std::unordered_set<crypto::hash> remove;
+ m_txpool_size = 0;
m_blockchain.for_all_txpool_txes([this, &remove, tx_size_limit](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) {
+ m_txpool_size += meta.blob_size;
if (meta.blob_size >= tx_size_limit) {
LOG_PRINT_L1("Transaction " << txid << " is too big (" << meta.blob_size << " bytes), removing it from pool");
remove.insert(txid);
@@ -1154,6 +1228,7 @@ namespace cryptonote
}
// remove tx from db first
m_blockchain.remove_txpool_tx(txid);
+ m_txpool_size -= txblob.size();
remove_transaction_keyimages(tx);
auto sorted_it = find_tx_in_sorted_container(txid);
if (sorted_it == m_txs_by_fee_and_receive_time.end())
@@ -1176,13 +1251,15 @@ namespace cryptonote
return n_removed;
}
//---------------------------------------------------------------------------------
- bool tx_memory_pool::init()
+ bool tx_memory_pool::init(size_t max_txpool_size)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
+ m_txpool_max_size = max_txpool_size ? max_txpool_size : DEFAULT_TXPOOL_MAX_SIZE;
m_txs_by_fee_and_receive_time.clear();
m_spent_key_images.clear();
+ m_txpool_size = 0;
std::vector<crypto::hash> remove;
bool r = m_blockchain.for_all_txpool_txes([this, &remove](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd) {
cryptonote::transaction tx;
@@ -1197,6 +1274,7 @@ namespace cryptonote
return false;
}
m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>(meta.fee / (double)meta.blob_size, meta.receive_time), txid);
+ m_txpool_size += meta.blob_size;
return true;
}, true);
if (!r)