From 41f727ce42d0fce9e40e4da7bf4abda92eef1016 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 19 Feb 2018 11:15:15 +0000 Subject: add RPC to get a histogram of outputs of a given amount --- src/cryptonote_core/blockchain.cpp | 46 ++++++++++++++++++++++++++++++++- src/cryptonote_core/blockchain.h | 23 ++++++++++++++++- src/cryptonote_core/cryptonote_core.cpp | 5 ++++ src/cryptonote_core/cryptonote_core.h | 6 +++++ 4 files changed, 78 insertions(+), 2 deletions(-) (limited to 'src/cryptonote_core') diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index a0031559b..0a6f1cdcd 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1903,6 +1903,45 @@ void Blockchain::get_output_key_mask_unlocked(const uint64_t& amount, const uint unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first)); } //------------------------------------------------------------------ +bool Blockchain::get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t &start_height, std::vector &distribution, uint64_t &base) const +{ + // rct outputs don't exist before v3 + if (amount == 0) + { + switch (m_nettype) + { + case STAGENET: start_height = stagenet_hard_forks[2].height; break; + case TESTNET: start_height = testnet_hard_forks[2].height; break; + case MAINNET: start_height = mainnet_hard_forks[2].height; break; + default: return false; + } + } + else + start_height = 0; + base = 0; + + const uint64_t real_start_height = start_height; + if (from_height > start_height) + start_height = from_height; + + distribution.clear(); + uint64_t db_height = m_db->height(); + if (start_height >= db_height) + return false; + distribution.resize(db_height - start_height, 0); + bool r = for_all_outputs(amount, [&](uint64_t height) { + CHECK_AND_ASSERT_MES(height >= real_start_height && height <= db_height, false, "Height not in expected range"); + if (height >= start_height) + distribution[height - start_height]++; + else + base++; + return true; + }); + if (!r) + return false; + return true; +} +//------------------------------------------------------------------ // This function takes a list of block hashes from another node // on the network to find where the split point is between us and them. // This is used to see what to send another node that needs to sync. @@ -4441,11 +4480,16 @@ bool Blockchain::for_all_transactions(std::functionfor_all_transactions(f); } -bool Blockchain::for_all_outputs(std::function f) const +bool Blockchain::for_all_outputs(std::function f) const { return m_db->for_all_outputs(f);; } +bool Blockchain::for_all_outputs(uint64_t amount, std::function f) const +{ + return m_db->for_all_outputs(amount, f);; +} + namespace cryptonote { template bool Blockchain::get_transactions(const std::vector&, std::list&, std::list&) const; } diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 1a52e20bf..4423199de 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -523,6 +523,17 @@ namespace cryptonote */ bool get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::request& req, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::response& res) const; + /** + * @brief gets per block distribution of outputs of a given amount + * + * @param amount the amount to get a ditribution for + * @param return-by-reference from_height the height before which we do not care about the data + * @param return-by-reference start_height the height of the first rct output + * @param return-by-reference distribution the start offset of the first rct output in this block (same as previous if none) + * @param return-by-reference base how many outputs of that amount are before the stated distribution + */ + bool get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t &start_height, std::vector &distribution, uint64_t &base) const; + /** * @brief gets the global indices for outputs from a given transaction * @@ -857,7 +868,17 @@ namespace cryptonote * * @return false if any output fails the check, otherwise true */ - bool for_all_outputs(std::function) const; + bool for_all_outputs(std::function) const; + + /** + * @brief perform a check on all outputs of a given amount in the blockchain + * + * @param amount the amount to iterate through + * @param std::function the check to perform, pass/fail + * + * @return false if any output fails the check, otherwise true + */ + bool for_all_outputs(uint64_t amount, std::function) const; /** * @brief get a reference to the BlockchainDB in use by Blockchain diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 8c0118803..a91cc9638 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -1105,6 +1105,11 @@ namespace cryptonote return m_blockchain_storage.get_random_rct_outs(req, res); } //----------------------------------------------------------------------------------------------- + bool core::get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t &start_height, std::vector &distribution, uint64_t &base) const + { + return m_blockchain_storage.get_output_distribution(amount, from_height, start_height, distribution, base); + } + //----------------------------------------------------------------------------------------------- bool core::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& indexs) const { return m_blockchain_storage.get_tx_outputs_gindexs(tx_id, indexs); diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index e1e430516..abf79be1d 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -571,6 +571,12 @@ namespace cryptonote */ bool get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::request& req, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::response& res) const; + /** + * @copydoc Blockchain::get_output_distribution + * + * @brief get per block distribution of outputs of a given amount + */ + bool get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t &start_height, std::vector &distribution, uint64_t &base) const; /** * @copydoc miner::pause -- cgit v1.2.3