From 8057a7c619e6a01362c1e517dc08e9ca4517e5c0 Mon Sep 17 00:00:00 2001 From: Lee *!* Clagett Date: Mon, 24 Jun 2024 14:25:35 -0400 Subject: [PATCH] Add (non-standard) 'daemon_status' endpoint to REST API --- src/rest_server.cpp | 41 ++++++++++++++++++++++++++++++++++++++ src/rpc/light_wallet.cpp | 24 ++++++++++++++++++++++ src/rpc/light_wallet.h | 43 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/src/rest_server.cpp b/src/rest_server.cpp index c75166a..cfb8529 100644 --- a/src/rest_server.cpp +++ b/src/rest_server.cpp @@ -37,6 +37,7 @@ #include "common/error.h" // monero/src #include "common/expect.h" // monero/src +#include "config.h" #include "crypto/crypto.h" // monero/src #include "cryptonote_config.h" // monero/src #include "db/data.h" @@ -165,6 +166,45 @@ namespace lws bool auto_accept_creation; }; + struct daemon_status + { + using request = rpc::daemon_status_request; + using response = rpc::daemon_status_response; + + static expect handle(request, const db::storage&, const rpc::client& gclient, const runtime_options&) + { + using info_rpc = cryptonote::rpc::GetInfo; + + const expect tclient = thread_client(gclient); + if (!tclient) + return tclient.error(); + if (*tclient == nullptr) + throw std::logic_error{"Unexpected rpc::client nullptr"}; + + info_rpc::Request daemon_req{}; + epee::byte_slice message = rpc::client::make_message("get_info", daemon_req); + MONERO_CHECK((*tclient)->send(std::move(message), std::chrono::seconds{2})); + + const auto daemon_resp = (*tclient)->receive(std::chrono::seconds{4}, MLWS_CURRENT_LOCATION); + if (!daemon_resp) + return daemon_resp.error(); + + response resp{ + daemon_resp->info.outgoing_connections_count, + daemon_resp->info.incoming_connections_count, + daemon_resp->info.height, + daemon_resp->info.target_height, + rpc::network_type(lws::config::network), + rpc::daemon_state::ok + }; + if (!resp.outgoing_connections_count && !resp.incoming_connections_count) + resp.state = rpc::daemon_state::no_connections; + else if (resp.target_height && (resp.target_height - resp.height) >= 5) + resp.state = rpc::daemon_state::synchronizing; + return resp; + } + }; + struct get_address_info { using request = rpc::account_credentials; @@ -910,6 +950,7 @@ namespace lws constexpr const endpoint endpoints[] = { + {"/daemon_status", call, 1024}, {"/get_address_info", call, 2 * 1024}, {"/get_address_txs", call, 2 * 1024}, {"/get_random_outs", call, 2 * 1024}, diff --git a/src/rpc/light_wallet.cpp b/src/rpc/light_wallet.cpp index 378d08c..6a47d2e 100644 --- a/src/rpc/light_wallet.cpp +++ b/src/rpc/light_wallet.cpp @@ -40,6 +40,7 @@ #include "ringct/rctOps.h" // monero/src #include "span.h" // monero/contrib/epee/include #include "util/random_outputs.h" +#include "wire.h" #include "wire/adapted/crypto.h" #include "wire/error.h" #include "wire/json.h" @@ -195,6 +196,29 @@ namespace lws convert_address(address, self.address); } + namespace rpc + { + namespace + { + constexpr const char* map_daemon_state[] = {"ok", "synchronizing", "no_connections"}; + constexpr const char* map_network_type[] = {"main", "test", "stage", "fake"}; + } + WIRE_DEFINE_ENUM(daemon_state, map_daemon_state); + WIRE_DEFINE_ENUM(network_type, map_network_type); + } + + void rpc::write_bytes(wire::json_writer& dest, const daemon_status_response& self) + { + wire::object(dest, + WIRE_FIELD(outgoing_connections_count), + WIRE_FIELD(incoming_connections_count), + WIRE_FIELD(height), + WIRE_FIELD(target_height), + WIRE_FIELD(network), + WIRE_FIELD(state) + ); + } + void rpc::write_bytes(wire::json_writer& dest, const new_subaddrs_response& self) { wire::object(dest, WIRE_FIELD(new_subaddrs), WIRE_FIELD(all_subaddrs)); diff --git a/src/rpc/light_wallet.h b/src/rpc/light_wallet.h index 9e9708e..cb977ed 100644 --- a/src/rpc/light_wallet.h +++ b/src/rpc/light_wallet.h @@ -33,8 +33,10 @@ #include #include -#include "common/expect.h" // monero/src -#include "crypto/crypto.h" // monero/src +#include "common/expect.h" // monero/src +#include "cryptonote_config.h" // monero/src +#include "cryptonote_basic/difficulty.h" // monero/src +#include "crypto/crypto.h" // monero/src #include "db/data.h" #include "rpc/rates.h" #include "util/fwd.h" @@ -65,6 +67,43 @@ namespace rpc void read_bytes(wire::json_reader&, account_credentials&); + enum class daemon_state : std::uint8_t + { + ok = 0, + synchronizing, + no_connections + }; + WIRE_DECLARE_ENUM(daemon_state); + + enum class network_type : std::uint8_t + { + main = 0, + test, + stage, + fake + }; + WIRE_DECLARE_ENUM(network_type); + + struct daemon_status_request + { + daemon_status_request() = delete; + }; + inline void read_bytes(const wire::reader&, const daemon_status_request&) + {} + + struct daemon_status_response + { + daemon_status_response() = delete; + std::uint64_t outgoing_connections_count; + std::uint64_t incoming_connections_count; + std::uint64_t height; + std::uint64_t target_height; + network_type network; + daemon_state state; + }; + void write_bytes(wire::json_writer&, const daemon_status_response&); + + struct new_subaddrs_response { new_subaddrs_response() = delete;