aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core/tx_pool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_core/tx_pool.cpp')
-rw-r--r--src/cryptonote_core/tx_pool.cpp163
1 files changed, 85 insertions, 78 deletions
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index 41c58fcb6..b12a329bb 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -80,9 +80,13 @@ namespace cryptonote
return amount * ACCEPT_THRESHOLD;
}
- uint64_t get_transaction_size_limit(uint8_t version)
+ uint64_t get_transaction_weight_limit(uint8_t version)
{
- return get_min_block_size(version) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
+ // from v8, limit a tx to 50% of the minimum block weight
+ if (version >= 8)
+ return get_min_block_weight(version) / 2 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
+ else
+ return get_min_block_weight(version) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
}
// This class is meant to create a batch when none currently exists.
@@ -102,12 +106,12 @@ namespace cryptonote
}
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
- tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs), m_txpool_max_size(DEFAULT_TXPOOL_MAX_SIZE), m_txpool_size(0), m_cookie(0)
+ tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs), m_txpool_max_weight(DEFAULT_TXPOOL_MAX_WEIGHT), m_txpool_weight(0), m_cookie(0)
{
}
//---------------------------------------------------------------------------------
- bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, size_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version)
+ bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, size_t tx_weight, tx_verification_context& tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version)
{
// this should already be called with that lock, but let's make it explicit for clarity
CRITICAL_REGION_LOCAL(m_transactions_lock);
@@ -173,17 +177,17 @@ namespace cryptonote
fee = tx.rct_signatures.txnFee;
}
- if (!kept_by_block && !m_blockchain.check_fee(blob_size, fee))
+ if (!kept_by_block && !m_blockchain.check_fee(tx_weight, fee))
{
tvc.m_verifivation_failed = true;
tvc.m_fee_too_low = true;
return false;
}
- size_t tx_size_limit = get_transaction_size_limit(version);
- if (!kept_by_block && blob_size > tx_size_limit)
+ size_t tx_weight_limit = get_transaction_weight_limit(version);
+ if (!kept_by_block && tx_weight > tx_weight_limit)
{
- LOG_PRINT_L1("transaction is too big: " << blob_size << " bytes, maximum size: " << tx_size_limit);
+ LOG_PRINT_L1("transaction is too heavy: " << tx_weight << " bytes, maximum weight: " << tx_weight_limit);
tvc.m_verifivation_failed = true;
tvc.m_too_big = true;
return false;
@@ -227,7 +231,7 @@ namespace cryptonote
// may become valid again, so ignore the failed inputs check.
if(kept_by_block)
{
- meta.blob_size = blob_size;
+ meta.weight = tx_weight;
meta.fee = fee;
meta.max_used_block_id = null_hash;
meta.max_used_block_height = 0;
@@ -248,7 +252,7 @@ namespace cryptonote
m_blockchain.add_txpool_tx(tx, meta);
if (!insert_key_images(tx, kept_by_block))
return false;
- m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)blob_size, receive_time), id);
+ m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id);
}
catch (const std::exception &e)
{
@@ -267,7 +271,7 @@ namespace cryptonote
}else
{
//update transactions container
- meta.blob_size = blob_size;
+ meta.weight = tx_weight;
meta.kept_by_block = kept_by_block;
meta.fee = fee;
meta.max_used_block_id = max_used_block_id;
@@ -290,7 +294,7 @@ namespace cryptonote
m_blockchain.add_txpool_tx(tx, meta);
if (!insert_key_images(tx, kept_by_block))
return false;
- m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)blob_size, receive_time), id);
+ m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id);
}
catch (const std::exception &e)
{
@@ -304,13 +308,13 @@ namespace cryptonote
}
tvc.m_verifivation_failed = false;
- m_txpool_size += blob_size;
+ m_txpool_weight += tx_weight;
++m_cookie;
- MINFO("Transaction added to pool: txid " << id << " bytes: " << blob_size << " fee/byte: " << (fee / (double)blob_size));
+ MINFO("Transaction added to pool: txid " << id << " weight: " << tx_weight << " fee/byte: " << (fee / (double)tx_weight));
- prune(m_txpool_max_size);
+ prune(m_txpool_max_weight);
return true;
}
@@ -321,26 +325,26 @@ namespace cryptonote
size_t blob_size = 0;
if (!get_transaction_hash(tx, h, blob_size) || blob_size == 0)
return false;
- return add_tx(tx, h, blob_size, tvc, keeped_by_block, relayed, do_not_relay, version);
+ return add_tx(tx, h, get_transaction_weight(tx, blob_size), tvc, keeped_by_block, relayed, do_not_relay, version);
}
//---------------------------------------------------------------------------------
- size_t tx_memory_pool::get_txpool_size() const
+ size_t tx_memory_pool::get_txpool_weight() const
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
- return m_txpool_size;
+ return m_txpool_weight;
}
//---------------------------------------------------------------------------------
- void tx_memory_pool::set_txpool_max_size(size_t bytes)
+ void tx_memory_pool::set_txpool_max_weight(size_t bytes)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
- m_txpool_max_size = bytes;
+ m_txpool_max_weight = bytes;
}
//---------------------------------------------------------------------------------
void tx_memory_pool::prune(size_t bytes)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
if (bytes == 0)
- bytes = m_txpool_max_size;
+ bytes = m_txpool_max_weight;
CRITICAL_REGION_LOCAL1(m_blockchain);
LockedTXN lock(m_blockchain);
bool changed = false;
@@ -349,7 +353,7 @@ namespace cryptonote
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)
+ if (m_txpool_weight <= bytes)
break;
try
{
@@ -374,11 +378,11 @@ namespace cryptonote
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);
+ MINFO("Pruning tx " << txid << " from txpool: weight: " << it->first.second << ", fee/byte: " << it->first.first);
m_blockchain.remove_txpool_tx(txid);
- m_txpool_size -= txblob.size();
+ m_txpool_weight -= it->first.second;
remove_transaction_keyimages(tx);
- MINFO("Pruned tx " << txid << " from txpool: size: " << it->first.second << ", fee/byte: " << it->first.first);
+ MINFO("Pruned tx " << txid << " from txpool: weight: " << it->first.second << ", fee/byte: " << it->first.first);
m_txs_by_fee_and_receive_time.erase(it--);
changed = true;
}
@@ -390,8 +394,8 @@ namespace cryptonote
}
if (changed)
++m_cookie;
- if (m_txpool_size > bytes)
- MINFO("Pool size after pruning is larger than limit: " << m_txpool_size << "/" << bytes);
+ if (m_txpool_weight > bytes)
+ MINFO("Pool weight after pruning is larger than limit: " << m_txpool_weight << "/" << bytes);
}
//---------------------------------------------------------------------------------
bool tx_memory_pool::insert_key_images(const transaction &tx, bool kept_by_block)
@@ -446,7 +450,7 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------------------------
- bool tx_memory_pool::take_tx(const crypto::hash &id, transaction &tx, size_t& blob_size, uint64_t& fee, bool &relayed, bool &do_not_relay, bool &double_spend_seen)
+ bool tx_memory_pool::take_tx(const crypto::hash &id, transaction &tx, size_t& tx_weight, uint64_t& fee, bool &relayed, bool &do_not_relay, bool &double_spend_seen)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
@@ -470,7 +474,7 @@ namespace cryptonote
MERROR("Failed to parse tx from txpool");
return false;
}
- blob_size = meta.blob_size;
+ tx_weight = meta.weight;
fee = meta.fee;
relayed = meta.relayed;
do_not_relay = meta.do_not_relay;
@@ -478,7 +482,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;
+ m_txpool_weight -= tx_weight;
remove_transaction_keyimages(tx);
}
catch (const std::exception &e)
@@ -552,7 +556,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();
+ m_txpool_weight -= get_transaction_weight(tx, bd.size());
remove_transaction_keyimages(tx);
}
}
@@ -670,7 +674,7 @@ namespace cryptonote
const uint64_t now = time(NULL);
backlog.reserve(m_blockchain.get_txpool_tx_count(include_unrelayed_txes));
m_blockchain.for_all_txpool_txes([&backlog, now](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
- backlog.push_back({meta.blob_size, meta.fee, meta.receive_time - now});
+ backlog.push_back({meta.weight, meta.fee, meta.receive_time - now});
return true;
}, false, include_unrelayed_txes);
}
@@ -682,15 +686,15 @@ namespace cryptonote
const uint64_t now = time(NULL);
std::map<uint64_t, txpool_histo> agebytes;
stats.txs_total = m_blockchain.get_txpool_tx_count(include_unrelayed_txes);
- std::vector<uint32_t> sizes;
- sizes.reserve(stats.txs_total);
- m_blockchain.for_all_txpool_txes([&stats, &sizes, now, &agebytes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
- sizes.push_back(meta.blob_size);
- stats.bytes_total += meta.blob_size;
- if (!stats.bytes_min || meta.blob_size < stats.bytes_min)
- stats.bytes_min = meta.blob_size;
- if (meta.blob_size > stats.bytes_max)
- stats.bytes_max = meta.blob_size;
+ std::vector<uint32_t> weights;
+ weights.reserve(stats.txs_total);
+ m_blockchain.for_all_txpool_txes([&stats, &weights, now, &agebytes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
+ weights.push_back(meta.weight);
+ stats.bytes_total += meta.weight;
+ if (!stats.bytes_min || meta.weight < stats.bytes_min)
+ stats.bytes_min = meta.weight;
+ if (meta.weight > stats.bytes_max)
+ stats.bytes_max = meta.weight;
if (!meta.relayed)
stats.num_not_relayed++;
stats.fee_total += meta.fee;
@@ -702,12 +706,12 @@ namespace cryptonote
stats.num_failing++;
uint64_t age = now - meta.receive_time + (now == meta.receive_time);
agebytes[age].txs++;
- agebytes[age].bytes += meta.blob_size;
+ agebytes[age].bytes += meta.weight;
if (meta.double_spend_seen)
++stats.num_double_spends;
return true;
}, false, include_unrelayed_txes);
- stats.bytes_med = epee::misc_utils::median(sizes);
+ stats.bytes_med = epee::misc_utils::median(weights);
if (stats.txs_total > 1)
{
/* looking for 98th percentile */
@@ -771,7 +775,8 @@ namespace cryptonote
return true;
}
txi.tx_json = obj_to_json_str(tx);
- txi.blob_size = meta.blob_size;
+ txi.blob_size = bd->size();
+ txi.weight = meta.weight;
txi.fee = meta.fee;
txi.kept_by_block = meta.kept_by_block;
txi.max_used_block_height = meta.max_used_block_height;
@@ -842,7 +847,8 @@ namespace cryptonote
return true;
}
txi.tx = tx;
- txi.blob_size = meta.blob_size;
+ txi.blob_size = bd->size();
+ txi.weight = meta.weight;
txi.fee = meta.fee;
txi.kept_by_block = meta.kept_by_block;
txi.max_used_block_height = meta.max_used_block_height;
@@ -1116,7 +1122,8 @@ namespace cryptonote
}
ss << obj_to_json_str(tx) << std::endl;
}
- ss << "blob_size: " << meta.blob_size << std::endl
+ ss << "blob_size: " << (short_format ? "-" : std::to_string(txblob->size())) << std::endl
+ << "weight: " << meta.weight << std::endl
<< "fee: " << print_money(meta.fee) << std::endl
<< "kept_by_block: " << (meta.kept_by_block ? 'T' : 'F') << std::endl
<< "double_spend_seen: " << (meta.double_spend_seen ? 'T' : 'F') << std::endl
@@ -1131,25 +1138,25 @@ namespace cryptonote
}
//---------------------------------------------------------------------------------
//TODO: investigate whether boolean return is appropriate
- bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee, uint64_t &expected_reward, uint8_t version)
+ bool tx_memory_pool::fill_block_template(block &bl, size_t median_weight, uint64_t already_generated_coins, size_t &total_weight, uint64_t &fee, uint64_t &expected_reward, uint8_t version)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
uint64_t best_coinbase = 0, coinbase = 0;
- total_size = 0;
+ total_weight = 0;
fee = 0;
//baseline empty block
- get_block_reward(median_size, total_size, already_generated_coins, best_coinbase, version);
+ get_block_reward(median_weight, total_weight, already_generated_coins, best_coinbase, version);
- size_t max_total_size_pre_v5 = (130 * median_size) / 100 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
- size_t max_total_size_v5 = 2 * median_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
- size_t max_total_size = version >= 5 ? max_total_size_v5 : max_total_size_pre_v5;
+ size_t max_total_weight_pre_v5 = (130 * median_weight) / 100 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
+ size_t max_total_weight_v5 = 2 * median_weight - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
+ size_t max_total_weight = version >= 5 ? max_total_weight_v5 : max_total_weight_pre_v5;
std::unordered_set<crypto::key_image> k_images;
- LOG_PRINT_L2("Filling block template, median size " << median_size << ", " << m_txs_by_fee_and_receive_time.size() << " txes in the pool");
+ LOG_PRINT_L2("Filling block template, median weight " << median_weight << ", " << m_txs_by_fee_and_receive_time.size() << " txes in the pool");
LockedTXN lock(m_blockchain);
@@ -1162,12 +1169,12 @@ namespace cryptonote
MERROR(" failed to find tx meta");
continue;
}
- LOG_PRINT_L2("Considering " << sorted_it->second << ", size " << meta.blob_size << ", current block size " << total_size << "/" << max_total_size << ", current coinbase " << print_money(best_coinbase));
+ LOG_PRINT_L2("Considering " << sorted_it->second << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_money(best_coinbase));
- // Can not exceed maximum block size
- if (max_total_size < total_size + meta.blob_size)
+ // Can not exceed maximum block weight
+ if (max_total_weight < total_weight + meta.weight)
{
- LOG_PRINT_L2(" would exceed maximum block size");
+ LOG_PRINT_L2(" would exceed maximum block weight");
continue;
}
@@ -1177,9 +1184,9 @@ namespace cryptonote
// If we're getting lower coinbase tx,
// stop including more tx
uint64_t block_reward;
- if(!get_block_reward(median_size, total_size + meta.blob_size, already_generated_coins, block_reward, version))
+ if(!get_block_reward(median_weight, total_weight + meta.weight, already_generated_coins, block_reward, version))
{
- LOG_PRINT_L2(" would exceed maximum block size");
+ LOG_PRINT_L2(" would exceed maximum block weight");
continue;
}
coinbase = block_reward + fee + meta.fee;
@@ -1191,11 +1198,11 @@ namespace cryptonote
}
else
{
- // If we've exceeded the penalty free size,
+ // If we've exceeded the penalty free weight,
// stop including more tx
- if (total_size > median_size)
+ if (total_weight > median_weight)
{
- LOG_PRINT_L2(" would exceed median block size");
+ LOG_PRINT_L2(" would exceed median block weight");
break;
}
}
@@ -1241,16 +1248,16 @@ namespace cryptonote
}
bl.tx_hashes.push_back(sorted_it->second);
- total_size += meta.blob_size;
+ total_weight += meta.weight;
fee += meta.fee;
best_coinbase = coinbase;
append_key_images(k_images, tx);
- LOG_PRINT_L2(" added, new block size " << total_size << "/" << max_total_size << ", coinbase " << print_money(best_coinbase));
+ LOG_PRINT_L2(" added, new block weight " << total_weight << "/" << max_total_weight << ", coinbase " << print_money(best_coinbase));
}
expected_reward = best_coinbase;
- LOG_PRINT_L2("Block template filled with " << bl.tx_hashes.size() << " txes, size "
- << total_size << "/" << max_total_size << ", coinbase " << print_money(best_coinbase)
+ LOG_PRINT_L2("Block template filled with " << bl.tx_hashes.size() << " txes, weight "
+ << total_weight << "/" << max_total_weight << ", coinbase " << print_money(best_coinbase)
<< " (including " << print_money(fee) << " in fees)");
return true;
}
@@ -1259,14 +1266,14 @@ namespace cryptonote
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
- size_t tx_size_limit = get_transaction_size_limit(version);
+ size_t tx_weight_limit = get_transaction_weight_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");
+ m_txpool_weight = 0;
+ m_blockchain.for_all_txpool_txes([this, &remove, tx_weight_limit](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) {
+ m_txpool_weight += meta.weight;
+ if (meta.weight > tx_weight_limit) {
+ LOG_PRINT_L1("Transaction " << txid << " is too big (" << meta.weight << " bytes), removing it from pool");
remove.insert(txid);
}
else if (m_blockchain.have_tx(txid)) {
@@ -1293,7 +1300,7 @@ namespace cryptonote
}
// remove tx from db first
m_blockchain.remove_txpool_tx(txid);
- m_txpool_size -= txblob.size();
+ m_txpool_weight -= get_transaction_weight(tx, 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())
@@ -1318,15 +1325,15 @@ namespace cryptonote
return n_removed;
}
//---------------------------------------------------------------------------------
- bool tx_memory_pool::init(size_t max_txpool_size)
+ bool tx_memory_pool::init(size_t max_txpool_weight)
{
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_txpool_max_weight = max_txpool_weight ? max_txpool_weight : DEFAULT_TXPOOL_MAX_WEIGHT;
m_txs_by_fee_and_receive_time.clear();
m_spent_key_images.clear();
- m_txpool_size = 0;
+ m_txpool_weight = 0;
std::vector<crypto::hash> remove;
// first add the not kept by block, then the kept by block,
@@ -1348,8 +1355,8 @@ namespace cryptonote
MFATAL("Failed to insert key images from txpool tx");
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;
+ m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>(meta.fee / (double)meta.weight, meta.receive_time), txid);
+ m_txpool_weight += meta.weight;
return true;
}, true);
if (!r)