Move tx pool stats struct out of rpc code

It makes no sense for the definition to be there (except that it was
for epee serialization purposes), so move it into tx_memory_pool where
it belongs, and convert it to json on the fly for the rpc method that
wants it.
This commit is contained in:
Jason Rhinelander 2021-08-12 21:32:03 -03:00 committed by Thomas Winget
parent 4c141e1e4a
commit ad79059b74
5 changed files with 56 additions and 90 deletions

View file

@ -1166,12 +1166,13 @@ namespace cryptonote
}, false, include_unrelayed_txes);
}
//------------------------------------------------------------------
void tx_memory_pool::get_transaction_stats(struct rpc::txpool_stats& stats, bool include_unrelayed_txes) const
tx_memory_pool::tx_stats tx_memory_pool::get_transaction_stats(bool include_unrelayed_txes) const
{
auto locks = tools::unique_locks(m_transactions_lock, m_blockchain);
tx_stats stats;
const uint64_t now = time(NULL);
std::map<uint64_t, rpc::txpool_histo> agebytes;
std::map<uint64_t, std::pair<uint32_t, uint64_t>> agebytes;
stats.txs_total = m_blockchain.get_txpool_tx_count(include_unrelayed_txes);
std::vector<uint32_t> weights;
weights.reserve(stats.txs_total);
@ -1192,8 +1193,8 @@ namespace cryptonote
if (meta.last_failed_height)
stats.num_failing++;
uint64_t age = now - meta.receive_time + (now == meta.receive_time);
agebytes[age].txs++;
agebytes[age].bytes += meta.weight;
agebytes[age].first++;
agebytes[age].second += meta.weight;
if (meta.double_spend_seen)
++stats.num_double_spends;
return true;
@ -1204,7 +1205,7 @@ namespace cryptonote
/* looking for 98th percentile */
size_t end = stats.txs_total * 0.02;
uint64_t delta, factor;
std::map<uint64_t, rpc::txpool_histo>::iterator it, i2;
decltype(agebytes.begin()) it;
if (end)
{
/* If enough txs, spread the first 98% of results across
@ -1217,7 +1218,7 @@ namespace cryptonote
*/
do {
--it;
cumulative_num += it->second.txs;
cumulative_num += it->second.first;
} while (it != agebytes.begin() && cumulative_num < end);
stats.histo_98pc = it->first;
factor = 9;
@ -1236,18 +1237,22 @@ namespace cryptonote
}
if (!delta)
delta = 1;
for (i2 = agebytes.begin(); i2 != it; i2++)
auto i2 = agebytes.begin();
for (; i2 != it; i2++)
{
size_t i = (i2->first * factor - 1) / delta;
stats.histo[i].txs += i2->second.txs;
stats.histo[i].bytes += i2->second.bytes;
stats.histo[i].first += i2->second.first;
stats.histo[i].second += i2->second.second;
}
for (; i2 != agebytes.end(); i2++)
{
stats.histo[factor].txs += i2->second.txs;
stats.histo[factor].bytes += i2->second.bytes;
auto& h = stats.histo[factor];
h.first += i2->second.first;
h.second += i2->second.second;
}
}
return stats;
}
//------------------------------------------------------------------
//TODO: investigate whether boolean return is appropriate

View file

@ -419,14 +419,34 @@ namespace cryptonote
*/
void get_transaction_backlog(std::vector<rpc::tx_backlog_entry>& backlog, bool include_unrelayed_txes = true) const;
/// Return type of get_transaction_stats()
struct tx_stats
{
uint64_t bytes_total; ///< Total size of all transactions in pool.
uint32_t bytes_min; ///< Min transaction size in pool.
uint32_t bytes_max; ///< Max transaction size in pool.
uint32_t bytes_med; ///< Median transaction size in pool.
uint64_t fee_total; ///< Total fee's in pool in atomic units.
uint64_t oldest; ///< Unix time of the oldest transaction in the pool.
uint32_t txs_total; ///< Total number of transactions.
uint32_t num_failing; ///< Bumber of failing transactions.
uint32_t num_10m; ///< Number of transactions in pool for more than 10 minutes.
uint32_t num_not_relayed; ///< Number of non-relayed transactions.
uint64_t histo_98pc; ///< the time 98% of txes are "younger" than.
std::vector<std::pair<uint32_t, uint64_t>> histo; ///< List of txpool histo [number of txes, size in bytes] pairs.
uint32_t num_double_spends; ///< Number of double spend transactions.
tx_stats(): bytes_total(0), bytes_min(0), bytes_max(0), bytes_med(0), fee_total(0), oldest(0), txs_total(0), num_failing(0), num_10m(0), num_not_relayed(0), histo_98pc(0), num_double_spends(0) {}
};
/**
* @brief get a summary statistics of all transaction hashes in the pool
*
* @param stats return-by-reference the pool statistics
* @param include_unrelayed_txes include unrelayed txes in the result
*
* @return txpool_stats struct of pool statistics
*/
void get_transaction_stats(struct rpc::txpool_stats& stats, bool include_unrelayed_txes = true) const;
tx_stats get_transaction_stats(bool include_unrelayed_txes = true) const;
/**
* @brief get information about all transactions and key images in the pool

View file

@ -1536,19 +1536,30 @@ namespace cryptonote::rpc {
return;
}
//------------------------------------------------------------------------------------------------------------------------------
void core_rpc_server::invoke(GET_TRANSACTION_POOL_STATS& get_transaction_pool_stats, rpc_context context)
void core_rpc_server::invoke(GET_TRANSACTION_POOL_STATS& stats, rpc_context context)
{
PERF_TIMER(on_get_transaction_pool_stats);
//TODO handle bootstrap daemon
//if (use_bootstrap_daemon_if_necessary<GET_TRANSACTION_POOL_STATS>(req, res))
//return res;
rpc::txpool_stats stats;
m_core.get_pool().get_transaction_stats(stats, context.admin);
get_transaction_pool_stats.response["pool_stats"] = stats
get_transaction_pool_stats.response["status"] = STATUS_OK;
LOG_PRINT_L0(get_transaction_pool_stats.response["status"]);
return;
auto txpool = m_core.get_pool().get_transaction_stats(context.admin);
stats.response["pool_stats"] = json{
{"bytes_total", txpool.bytes_total},
{"bytes_min", txpool.bytes_min},
{"bytes_max", txpool.bytes_max},
{"bytes_med", txpool.bytes_med},
{"fee_total", txpool.fee_total},
{"oldest", txpool.oldest},
{"txs_total", txpool.txs_total},
{"num_failing", txpool.num_failing},
{"num_10m", txpool.num_10m},
{"num_not_relayed", txpool.num_not_relayed},
{"histo_98pc", txpool.histo_98pc},
{"histo", txpool.histo},
{"num_double_spends", txpool.num_double_spends}};
stats.response["status"] = STATUS_OK;
}
//------------------------------------------------------------------------------------------------------------------------------
SET_BOOTSTRAP_DAEMON::response core_rpc_server::invoke(SET_BOOTSTRAP_DAEMON::request&& req, rpc_context context)

View file

@ -497,28 +497,6 @@ KV_SERIALIZE_MAP_CODE_BEGIN(GET_TRANSACTION_POOL_HASHES_BIN::response)
KV_SERIALIZE(untrusted)
KV_SERIALIZE_MAP_CODE_END()
KV_SERIALIZE_MAP_CODE_BEGIN(txpool_histo)
KV_SERIALIZE(txs)
KV_SERIALIZE(bytes)
KV_SERIALIZE_MAP_CODE_END()
KV_SERIALIZE_MAP_CODE_BEGIN(txpool_stats)
KV_SERIALIZE(bytes_total)
KV_SERIALIZE(bytes_min)
KV_SERIALIZE(bytes_max)
KV_SERIALIZE(bytes_med)
KV_SERIALIZE(fee_total)
KV_SERIALIZE(oldest)
KV_SERIALIZE(txs_total)
KV_SERIALIZE(num_failing)
KV_SERIALIZE(num_10m)
KV_SERIALIZE(num_not_relayed)
KV_SERIALIZE(histo_98pc)
KV_SERIALIZE(histo)
KV_SERIALIZE(num_double_spends)
KV_SERIALIZE_MAP_CODE_END()
KV_SERIALIZE_MAP_CODE_BEGIN(GET_BLOCK_HEADERS_RANGE::request)
KV_SERIALIZE(start_height)

View file

@ -1298,54 +1298,6 @@ namespace cryptonote::rpc {
static constexpr auto names() { return NAMES("get_txpool_backlog"); }
};
OXEN_RPC_DOC_INTROSPECT
struct txpool_histo
{
uint32_t txs; // Number of transactions.
uint64_t bytes; // Size in bytes.
KV_MAP_SERIALIZABLE
};
OXEN_RPC_DOC_INTROSPECT
struct txpool_stats
{
uint64_t bytes_total; // Total size of all transactions in pool.
uint32_t bytes_min; // Min transaction size in pool.
uint32_t bytes_max; // Max transaction size in pool.
uint32_t bytes_med; // Median transaction size in pool.
uint64_t fee_total; // Total fee's in pool in atomic units.
uint64_t oldest; // Unix time of the oldest transaction in the pool.
uint32_t txs_total; // Total number of transactions.
uint32_t num_failing; // Bumber of failing transactions.
uint32_t num_10m; // Number of transactions in pool for more than 10 minutes.
uint32_t num_not_relayed; // Number of non-relayed transactions.
uint64_t histo_98pc; // the time 98% of txes are "younger" than.
std::vector<txpool_histo> histo; // List of txpool histo.
uint32_t num_double_spends; // Number of double spend transactions.
txpool_stats(): bytes_total(0), bytes_min(0), bytes_max(0), bytes_med(0), fee_total(0), oldest(0), txs_total(0), num_failing(0), num_10m(0), num_not_relayed(0), histo_98pc(0), num_double_spends(0) {}
KV_MAP_SERIALIZABLE
};
//void to_json(nlohmann::json& j, const txpool_stats& txpool) {
//j = nlohmann::json{{"bytes_total", txpool.bytes_total},
//{"bytes_min", txpool.bytes_min},
//{"bytes_max", txpool.bytes_max},
//{"bytes_med", txpool.bytes_med},
//{"fee_total", txpool.fee_total},
//{"oldest", txpool.oldest},
//{"txs_total", txpool.txs_total},
//{"num_failing", txpool.num_failing},
//{"num_10m", txpool.num_10m},
//{"num_not_relayed", txpool.num_not_relayed},
//{"histo_98pc", txpool.histo_98pc},
//{"histo", txpool.histo},
//{"num_double_spends", txpool.num_double_spends}};
//}
//-----------------------------------------------
/// Get the transaction pool statistics.
///