New RPC and daemon command to get output histogram
This is a list of existing output amounts along with the number of outputs of that amount in the blockchain. The daemon command takes: - no parameters: all outputs with at least 3 instances - one parameter: all outputs with at least that many instances - two parameters: all outputs within that many instances The default starts at 3 to avoid massive spamming of all dust outputs in the blockchain, and is the current minimum mixin requirement. An optional vector of amounts may be passed, to request histogram only for those outputs.
This commit is contained in:
@@ -2692,6 +2692,63 @@ void BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const std::
|
||||
LOG_PRINT_L3("db3: " << db3);
|
||||
}
|
||||
|
||||
std::map<uint64_t, uint64_t> BlockchainLMDB::get_output_histogram(const std::vector<uint64_t> &amounts) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
||||
TXN_PREFIX_RDONLY();
|
||||
RCURSOR(output_amounts);
|
||||
|
||||
std::map<uint64_t, uint64_t> histogram;
|
||||
MDB_val k;
|
||||
MDB_val v;
|
||||
|
||||
if (amounts.empty())
|
||||
{
|
||||
MDB_cursor_op op = MDB_FIRST;
|
||||
while (1)
|
||||
{
|
||||
int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, op);
|
||||
op = MDB_NEXT_NODUP;
|
||||
if (ret == MDB_NOTFOUND)
|
||||
break;
|
||||
if (ret)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to enumerate outputs: ", ret).c_str()));
|
||||
mdb_size_t num_elems = 0;
|
||||
mdb_cursor_count(m_cur_output_amounts, &num_elems);
|
||||
uint64_t amount = *(const uint64_t*)k.mv_data;
|
||||
histogram[amount] = num_elems;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto &amount: amounts)
|
||||
{
|
||||
MDB_val_copy<uint64_t> k(amount);
|
||||
int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_SET);
|
||||
if (ret == MDB_NOTFOUND)
|
||||
{
|
||||
histogram[amount] = 0;
|
||||
}
|
||||
else if (ret == MDB_SUCCESS)
|
||||
{
|
||||
mdb_size_t num_elems = 0;
|
||||
mdb_cursor_count(m_cur_output_amounts, &num_elems);
|
||||
histogram[amount] = num_elems;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw0(DB_ERROR(lmdb_error("Failed to enumerate outputs: ", ret).c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TXN_POSTFIX_RDONLY();
|
||||
|
||||
return histogram;
|
||||
}
|
||||
|
||||
void BlockchainLMDB::check_hard_fork_info()
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
|
||||
@@ -280,6 +280,16 @@ public:
|
||||
virtual void pop_block(block& blk, std::vector<transaction>& txs);
|
||||
|
||||
virtual bool can_thread_bulk_indices() const { return true; }
|
||||
|
||||
/**
|
||||
* @brief return a histogram of outputs on the blockchain
|
||||
*
|
||||
* @param amounts optional set of amounts to lookup
|
||||
*
|
||||
* @return a set of amount/instances
|
||||
*/
|
||||
std::map<uint64_t, uint64_t> get_output_histogram(const std::vector<uint64_t> &amounts) const;
|
||||
|
||||
private:
|
||||
void do_resize(uint64_t size_increase=0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user