mirror of https://github.com/oxen-io/oxen-core.git
GET_OUTPUT_HISTOGRAM
This commit is contained in:
parent
4013cb5115
commit
8b3d2371bb
|
@ -1198,24 +1198,21 @@ bool rpc_command_executor::flush_txpool(std::string txid)
|
|||
|
||||
bool rpc_command_executor::output_histogram(const std::vector<uint64_t> &amounts, uint64_t min_count, uint64_t max_count)
|
||||
{
|
||||
GET_OUTPUT_HISTOGRAM::request req{};
|
||||
GET_OUTPUT_HISTOGRAM::response res{};
|
||||
|
||||
req.amounts = amounts;
|
||||
req.min_count = min_count;
|
||||
req.max_count = max_count;
|
||||
req.unlocked = false;
|
||||
req.recent_cutoff = 0;
|
||||
|
||||
if (!invoke<GET_OUTPUT_HISTOGRAM>(std::move(req), res, "Failed to retrieve output histogram"))
|
||||
return false;
|
||||
|
||||
std::sort(res.histogram.begin(), res.histogram.end(),
|
||||
auto maybe_histogram= try_running([this, &amounts, min_count, max_count]
|
||||
{ return invoke<GET_OUTPUT_HISTOGRAM>(
|
||||
json{{"amounts", amounts},
|
||||
{"min_count", min_count},
|
||||
{"max_count", max_count},
|
||||
{"unlocked", false},
|
||||
{"recent_cutoff", 0}});
|
||||
}, "Failed to retrieve output histogram");
|
||||
if (!maybe_histogram)
|
||||
return false;
|
||||
std::vector<GET_OUTPUT_HISTOGRAM::entry> histogram = (*maybe_histogram)["histogram"];
|
||||
std::sort(histogram.begin(), histogram.end(),
|
||||
[](const auto& e1, const auto& e2)->bool { return e1.total_instances < e2.total_instances; });
|
||||
for (const auto &e: res.histogram)
|
||||
{
|
||||
for (const auto &e: histogram)
|
||||
tools::msg_writer() << e.total_instances << " " << cryptonote::print_money(e.amount);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1791,39 +1791,45 @@ namespace cryptonote::rpc {
|
|||
: STATUS_OK;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
GET_OUTPUT_HISTOGRAM::response core_rpc_server::invoke(GET_OUTPUT_HISTOGRAM::request&& req, rpc_context context)
|
||||
void core_rpc_server::invoke(GET_OUTPUT_HISTOGRAM& get_output_histogram, rpc_context context)
|
||||
{
|
||||
GET_OUTPUT_HISTOGRAM::response res{};
|
||||
|
||||
PERF_TIMER(on_get_output_histogram);
|
||||
|
||||
if (!context.admin && req.recent_cutoff > 0 && req.recent_cutoff < (uint64_t)time(NULL) - OUTPUT_HISTOGRAM_RECENT_CUTOFF_RESTRICTION)
|
||||
if (!context.admin && get_output_histogram.request.recent_cutoff > 0 && get_output_histogram.request.recent_cutoff < (uint64_t)time(NULL) - OUTPUT_HISTOGRAM_RECENT_CUTOFF_RESTRICTION)
|
||||
{
|
||||
res.status = "Recent cutoff is too old";
|
||||
return res;
|
||||
get_output_histogram.response["status"] = "Recent cutoff is too old";
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> histogram;
|
||||
try
|
||||
{
|
||||
histogram = m_core.get_blockchain_storage().get_output_histogram(req.amounts, req.unlocked, req.recent_cutoff, req.min_count);
|
||||
histogram = m_core.get_blockchain_storage().get_output_histogram(
|
||||
get_output_histogram.request.amounts,
|
||||
get_output_histogram.request.unlocked,
|
||||
get_output_histogram.request.recent_cutoff,
|
||||
get_output_histogram.request.min_count
|
||||
);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
res.status = "Failed to get output histogram";
|
||||
return res;
|
||||
get_output_histogram.response["status"] = "Failed to get output histogram";
|
||||
return;
|
||||
}
|
||||
|
||||
res.histogram.clear();
|
||||
res.histogram.reserve(histogram.size());
|
||||
for (const auto &i: histogram)
|
||||
std::vector<GET_OUTPUT_HISTOGRAM::entry> response_histogram;
|
||||
response_histogram.reserve(histogram.size());
|
||||
for (const auto &[amount, histogram_tuple]: histogram)
|
||||
{
|
||||
if (std::get<0>(i.second) >= req.min_count && (std::get<0>(i.second) <= req.max_count || req.max_count == 0))
|
||||
res.histogram.push_back(GET_OUTPUT_HISTOGRAM::entry(i.first, std::get<0>(i.second), std::get<1>(i.second), std::get<2>(i.second)));
|
||||
auto& [total_instances, unlocked_instances, recent_instances] = histogram_tuple;
|
||||
|
||||
if (total_instances >= get_output_histogram.request.min_count && (total_instances <= get_output_histogram.request.max_count || get_output_histogram.request.max_count == 0))
|
||||
response_histogram.push_back(GET_OUTPUT_HISTOGRAM::entry{amount, total_instances, unlocked_instances, recent_instances});
|
||||
}
|
||||
|
||||
res.status = STATUS_OK;
|
||||
return res;
|
||||
get_output_histogram.response["histogram"] = response_histogram;
|
||||
get_output_histogram.response["status"] = STATUS_OK;
|
||||
return;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
void core_rpc_server::invoke(GET_VERSION& version, rpc_context context)
|
||||
|
|
|
@ -253,6 +253,7 @@ namespace cryptonote::rpc {
|
|||
void invoke(GET_SERVICE_NODE_REGISTRATION_CMD_RAW& get_service_node_registration_cmd_raw, rpc_context context);
|
||||
void invoke(GET_QUORUM_STATE& get_quorum_state, rpc_context context);
|
||||
void invoke(GET_ALTERNATE_CHAINS& get_alternate_chains, rpc_context context);
|
||||
void invoke(GET_OUTPUT_HISTOGRAM& get_output_histogram, rpc_context context);
|
||||
|
||||
// Deprecated Monero NIH binary endpoints:
|
||||
GET_ALT_BLOCKS_HASHES_BIN::response invoke(GET_ALT_BLOCKS_HASHES_BIN::request&& req, rpc_context context);
|
||||
|
@ -267,7 +268,6 @@ namespace cryptonote::rpc {
|
|||
GET_OUTPUT_DISTRIBUTION::response invoke(GET_OUTPUT_DISTRIBUTION::request&& req, rpc_context context, bool binary = false);
|
||||
|
||||
// FIXME: unconverted JSON RPC endpoints:
|
||||
GET_OUTPUT_HISTOGRAM::response invoke(GET_OUTPUT_HISTOGRAM::request&& req, rpc_context context);
|
||||
GET_SERVICE_NODE_REGISTRATION_CMD::response invoke(GET_SERVICE_NODE_REGISTRATION_CMD::request&& req, rpc_context context);
|
||||
ONS_NAMES_TO_OWNERS::response invoke(ONS_NAMES_TO_OWNERS::request&& req, rpc_context context);
|
||||
ONS_OWNERS_TO_NAMES::response invoke(ONS_OWNERS_TO_NAMES::request&& req, rpc_context context);
|
||||
|
|
|
@ -509,4 +509,12 @@ namespace cryptonote::rpc {
|
|||
get_values(in, "height", get_block.request.height);
|
||||
get_values(in, "fill_pow_hash", get_block.request.fill_pow_hash);
|
||||
}
|
||||
|
||||
void parse_request(GET_OUTPUT_HISTOGRAM& get_output_histogram, rpc_input in) {
|
||||
get_values(in, "amounts", get_output_histogram.request.amounts);
|
||||
get_values(in, "min_count", get_output_histogram.request.min_count);
|
||||
get_values(in, "max_count", get_output_histogram.request.max_count);
|
||||
get_values(in, "unlocked", get_output_histogram.request.unlocked);
|
||||
get_values(in, "recent_cutoff", get_output_histogram.request.recent_cutoff);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,4 +44,5 @@ namespace cryptonote::rpc {
|
|||
void parse_request(GET_BLOCK_HEADERS_RANGE& get_block_headers_range, rpc_input in);
|
||||
void parse_request(GET_BLOCK_HEADER_BY_HEIGHT& get_block_header_by_height, rpc_input in);
|
||||
void parse_request(GET_BLOCK& get_block, rpc_input in);
|
||||
void parse_request(GET_OUTPUT_HISTOGRAM& get_output_histogram, rpc_input in);
|
||||
}
|
||||
|
|
|
@ -98,6 +98,23 @@ void from_json(const nlohmann::json& j, GET_ALTERNATE_CHAINS::chain_info& c)
|
|||
j.at("main_chain_parent_block").get_to(c.main_chain_parent_block);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json& j, const GET_OUTPUT_HISTOGRAM::entry& e)
|
||||
{
|
||||
j = nlohmann::json{
|
||||
{"amount", e.amount},
|
||||
{"total_instances", e.total_instances},
|
||||
{"unlocked_instances", e.unlocked_instances},
|
||||
{"recent_instances", e.recent_instances},
|
||||
};
|
||||
}
|
||||
void from_json(const nlohmann::json& j, GET_OUTPUT_HISTOGRAM::entry& e)
|
||||
{
|
||||
j.at("amount").get_to(e.amount);
|
||||
j.at("total_instances").get_to(e.total_instances);
|
||||
j.at("unlocked_instances").get_to(e.unlocked_instances);
|
||||
j.at("recent_instances").get_to(e.recent_instances);
|
||||
};
|
||||
|
||||
KV_SERIALIZE_MAP_CODE_BEGIN(STATUS)
|
||||
KV_SERIALIZE(status)
|
||||
KV_SERIALIZE_MAP_CODE_END()
|
||||
|
@ -132,29 +149,6 @@ KV_SERIALIZE_MAP_CODE_BEGIN(block_header_response)
|
|||
KV_SERIALIZE_MAP_CODE_END()
|
||||
|
||||
|
||||
KV_SERIALIZE_MAP_CODE_BEGIN(GET_OUTPUT_HISTOGRAM::request)
|
||||
KV_SERIALIZE(amounts);
|
||||
KV_SERIALIZE(min_count);
|
||||
KV_SERIALIZE(max_count);
|
||||
KV_SERIALIZE(unlocked);
|
||||
KV_SERIALIZE(recent_cutoff);
|
||||
KV_SERIALIZE_MAP_CODE_END()
|
||||
|
||||
|
||||
KV_SERIALIZE_MAP_CODE_BEGIN(GET_OUTPUT_HISTOGRAM::entry)
|
||||
KV_SERIALIZE(amount);
|
||||
KV_SERIALIZE(total_instances);
|
||||
KV_SERIALIZE(unlocked_instances);
|
||||
KV_SERIALIZE(recent_instances);
|
||||
KV_SERIALIZE_MAP_CODE_END()
|
||||
|
||||
|
||||
KV_SERIALIZE_MAP_CODE_BEGIN(GET_OUTPUT_HISTOGRAM::response)
|
||||
KV_SERIALIZE(status)
|
||||
KV_SERIALIZE(histogram)
|
||||
KV_SERIALIZE_MAP_CODE_END()
|
||||
|
||||
|
||||
KV_SERIALIZE_MAP_CODE_BEGIN(GET_OUTPUT_DISTRIBUTION::request)
|
||||
KV_SERIALIZE(amounts)
|
||||
KV_SERIALIZE_OPT(from_height, (uint64_t)0)
|
||||
|
|
|
@ -399,7 +399,6 @@ namespace cryptonote::rpc {
|
|||
/// Outputs
|
||||
///
|
||||
/// - \p status General RPC status string. `"OK"` means everything looks good.
|
||||
/// untrusted ('true'), or when the daemon is fully synced ('false').
|
||||
/// - \p spent_status array of status codes returned in the same order as the `key_images` input.
|
||||
/// Each value is one of:
|
||||
/// - \p 0 the key image is unspent
|
||||
|
@ -434,7 +433,6 @@ namespace cryptonote::rpc {
|
|||
/// Output values available from a public RPC endpoint:
|
||||
///
|
||||
/// - \p status General RPC status string. `"OK"` means everything looks good.
|
||||
/// untrusted ('true'), or when the daemon is fully synced ('false').
|
||||
/// - \p outs List of outkey information; if `as_tuple` is not set then these are dicts containing
|
||||
/// keys:
|
||||
/// - \p key The public key of the output.
|
||||
|
@ -473,7 +471,6 @@ namespace cryptonote::rpc {
|
|||
/// Output values available from a public RPC endpoint:
|
||||
///
|
||||
/// - \p status General RPC status string. `"OK"` means everything looks good.
|
||||
/// untrusted ('true'), or when the daemon is fully synced ('false').
|
||||
/// - \p reason String containing additional information on why a transaction failed.
|
||||
/// - \p blink_status Set to the result of submitting this transaction to the Blink quorum. 1
|
||||
/// means the quorum rejected the transaction; 2 means the quorum accepted it; 3 means there was
|
||||
|
@ -627,7 +624,6 @@ namespace cryptonote::rpc {
|
|||
/// - \p block_size_median Median block size of latest 100 blocks.
|
||||
/// - \p ons_counts ONS registration counts, as a three-element list: [session, wallet, lokinet]
|
||||
/// - \p offline Indicates that the node is offline, if true. Omitted for online nodes.
|
||||
/// not trusted (`true`). Omitted for non-bootstrap responses.
|
||||
/// - \p database_size Current size of Blockchain data. Over public RPC this is rounded up to the
|
||||
/// next-largest GB value.
|
||||
/// - \p version Current version of this daemon, as a string. For a public node this will just be
|
||||
|
@ -958,7 +954,6 @@ namespace cryptonote::rpc {
|
|||
///
|
||||
/// - \p status General RPC status string. `"OK"` means everything looks good.
|
||||
/// - \p tx_hashes List of transaction hashes,
|
||||
/// trusted (`true`), or when the daemon is fully synced (`false`).
|
||||
struct GET_TRANSACTION_POOL_HASHES : PUBLIC, LEGACY, NO_ARGS
|
||||
{
|
||||
static constexpr auto names() { return NAMES("get_transaction_pool_hashes"); }
|
||||
|
@ -1001,7 +996,6 @@ namespace cryptonote::rpc {
|
|||
/// `histo_98pc`.
|
||||
/// - \p histo_98pc See `histo` for details.
|
||||
/// - \p histo_max See `histo` for details.
|
||||
/// trusted (`true`), or when the daemon is fully synced (`false`).
|
||||
struct GET_TRANSACTION_POOL_STATS : PUBLIC, LEGACY
|
||||
{
|
||||
static constexpr auto names() { return NAMES("get_transaction_pool_stats"); }
|
||||
|
@ -1180,7 +1174,6 @@ namespace cryptonote::rpc {
|
|||
/// Output values available from a public RPC endpoint:
|
||||
///
|
||||
/// - \p status General RPC status string. `"OK"` means everything looks good.
|
||||
/// untrusted ('true'), or when the daemon is fully synced ('false').
|
||||
/// - \p version The major block version for the fork.
|
||||
/// - \p enabled Indicates whether the hard fork is enforced on the blockchain (that is, whether
|
||||
/// the blockchain height is at or above the requested hardfork).
|
||||
|
@ -1285,23 +1278,37 @@ namespace cryptonote::rpc {
|
|||
} request;
|
||||
};
|
||||
|
||||
OXEN_RPC_DOC_INTROSPECT
|
||||
// Get a histogram of output amounts. For all amounts (possibly filtered by parameters),
|
||||
// gives the number of outputs on the chain for that amount. RingCT outputs counts as 0 amount.
|
||||
/// Get a histogram of output amounts. For all amounts (possibly filtered by parameters),
|
||||
/// gives the number of outputs on the chain for that amount. RingCT outputs counts as 0 amount.
|
||||
///
|
||||
/// Inputs:
|
||||
///
|
||||
/// - \p amounts list of amounts in Atomic Units.
|
||||
/// - \p min_count The minimum amounts you are requesting.
|
||||
/// - \p max_count The maximum amounts you are requesting.
|
||||
/// - \p unlocked Look for locked only.
|
||||
/// - \p recent_cutoff
|
||||
///
|
||||
/// Output values available from a public RPC endpoint:
|
||||
///
|
||||
/// - \p status General RPC status string. `"OK"` means everything looks good.
|
||||
/// - \p histogram List of histogram entries. Each element is structured as follows:
|
||||
/// - \p uint64_t amount Output amount in atomic units.
|
||||
/// - \p uint64_t total_instances
|
||||
/// - \p uint64_t unlocked_instances
|
||||
/// - \p uint64_t recent_instances
|
||||
struct GET_OUTPUT_HISTOGRAM : PUBLIC
|
||||
{
|
||||
static constexpr auto names() { return NAMES("get_output_histogram"); }
|
||||
|
||||
struct request
|
||||
struct request_parameters
|
||||
{
|
||||
std::vector<uint64_t> amounts; // list of amounts in Atomic Units.
|
||||
uint64_t min_count; // The minimum amounts you are requesting.
|
||||
uint64_t max_count; // The maximum amounts you are requesting.
|
||||
bool unlocked; // Look for locked only.
|
||||
uint64_t recent_cutoff;
|
||||
|
||||
KV_MAP_SERIALIZABLE
|
||||
};
|
||||
} request;
|
||||
|
||||
struct entry
|
||||
{
|
||||
|
@ -1309,22 +1316,10 @@ namespace cryptonote::rpc {
|
|||
uint64_t total_instances;
|
||||
uint64_t unlocked_instances;
|
||||
uint64_t recent_instances;
|
||||
|
||||
KV_MAP_SERIALIZABLE
|
||||
|
||||
entry(uint64_t amount, uint64_t total_instances, uint64_t unlocked_instances, uint64_t recent_instances):
|
||||
amount(amount), total_instances(total_instances), unlocked_instances(unlocked_instances), recent_instances(recent_instances) {}
|
||||
entry() = default;
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string status; // General RPC error code. "OK" means everything looks good.
|
||||
std::vector<entry> histogram; // List of histogram entries:
|
||||
|
||||
KV_MAP_SERIALIZABLE
|
||||
};
|
||||
};
|
||||
void to_json(nlohmann::json& j, const GET_OUTPUT_HISTOGRAM::entry& c);
|
||||
void from_json(const nlohmann::json& j, GET_OUTPUT_HISTOGRAM::entry& c);
|
||||
|
||||
/// Get current RPC protocol version.
|
||||
///
|
||||
|
@ -1334,7 +1329,6 @@ namespace cryptonote::rpc {
|
|||
///
|
||||
/// - \p status General RPC status string. `"OK"` means everything looks good.
|
||||
/// - \p version RPC current version.
|
||||
/// trusted (`true`), or when the daemon is fully synced
|
||||
struct GET_VERSION : PUBLIC, NO_ARGS
|
||||
{
|
||||
static constexpr auto names() { return NAMES("get_version"); }
|
||||
|
@ -1387,7 +1381,6 @@ namespace cryptonote::rpc {
|
|||
/// - \p blink_fee_fixed Fixed blink fee in addition to the per-output and per-byte amounts. The
|
||||
/// portion of the overall blink fee above the overall base fee is burned.
|
||||
/// - \p quantization_mask
|
||||
/// trusted (`true`), or when the daemon is fully synced (`false`).
|
||||
struct GET_BASE_FEE_ESTIMATE : PUBLIC
|
||||
{
|
||||
static constexpr auto names() { return NAMES("get_fee_estimate"); }
|
||||
|
|
Loading…
Reference in New Issue