mirror of
https://github.com/oxen-io/oxen-core.git
synced 2023-12-14 02:22:56 +01:00
RPC: +peerlist, -publicnodes
Updates GET_PEER_LIST to new RPC. Removes GET_PUBLIC_NODES because we don't use this option at all in oxend. (At the point where we need a decentralized public node repository we'll almost certainly want to use the service node network to do it, not the p2p layer).
This commit is contained in:
parent
e1ef4a44e4
commit
ff0c76d7f3
|
@ -225,6 +225,7 @@ namespace net_utils
|
||||||
|
|
||||||
virtual std::string str() const = 0;
|
virtual std::string str() const = 0;
|
||||||
virtual std::string host_str() const = 0;
|
virtual std::string host_str() const = 0;
|
||||||
|
virtual uint16_t port() const = 0;
|
||||||
virtual bool is_loopback() const = 0;
|
virtual bool is_loopback() const = 0;
|
||||||
virtual bool is_local() const = 0;
|
virtual bool is_local() const = 0;
|
||||||
virtual address_type get_type_id() const = 0;
|
virtual address_type get_type_id() const = 0;
|
||||||
|
@ -255,6 +256,7 @@ namespace net_utils
|
||||||
|
|
||||||
virtual std::string str() const override { return value.str(); }
|
virtual std::string str() const override { return value.str(); }
|
||||||
virtual std::string host_str() const override { return value.host_str(); }
|
virtual std::string host_str() const override { return value.host_str(); }
|
||||||
|
virtual uint16_t port() const override { return value.port(); }
|
||||||
virtual bool is_loopback() const override { return value.is_loopback(); }
|
virtual bool is_loopback() const override { return value.is_loopback(); }
|
||||||
virtual bool is_local() const override { return value.is_local(); }
|
virtual bool is_local() const override { return value.is_local(); }
|
||||||
virtual address_type get_type_id() const override { return value.get_type_id(); }
|
virtual address_type get_type_id() const override { return value.get_type_id(); }
|
||||||
|
@ -303,6 +305,7 @@ namespace net_utils
|
||||||
bool is_same_host(const network_address &other) const;
|
bool is_same_host(const network_address &other) const;
|
||||||
std::string str() const { return self ? self->str() : "<none>"; }
|
std::string str() const { return self ? self->str() : "<none>"; }
|
||||||
std::string host_str() const { return self ? self->host_str() : "<none>"; }
|
std::string host_str() const { return self ? self->host_str() : "<none>"; }
|
||||||
|
uint16_t port() const { return self ? self->port() : 0; }
|
||||||
bool is_loopback() const { return self ? self->is_loopback() : false; }
|
bool is_loopback() const { return self ? self->is_loopback() : false; }
|
||||||
bool is_local() const { return self ? self->is_local() : false; }
|
bool is_local() const { return self ? self->is_local() : false; }
|
||||||
address_type get_type_id() const { return self ? self->get_type_id() : address_type::invalid; }
|
address_type get_type_id() const { return self ? self->get_type_id() : address_type::invalid; }
|
||||||
|
|
|
@ -112,24 +112,6 @@ namespace {
|
||||||
return input_line_result::yes;
|
return input_line_result::yes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_peer(std::string const & prefix, GET_PEER_LIST::peer const & peer, bool pruned_only, bool publicrpc_only)
|
|
||||||
{
|
|
||||||
if (pruned_only && peer.pruning_seed == 0)
|
|
||||||
return;
|
|
||||||
if (publicrpc_only && peer.rpc_port == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
time_t now = std::time(nullptr);
|
|
||||||
time_t last_seen = static_cast<time_t>(peer.last_seen);
|
|
||||||
|
|
||||||
std::string elapsed = peer.last_seen == 0 ? "never" : epee::misc_utils::get_time_interval_string(now - last_seen);
|
|
||||||
std::string id_str = epee::string_tools::pad_string(epee::string_tools::to_string_hex(peer.id), 16, '0', true);
|
|
||||||
std::string addr_str = peer.host + ":" + std::to_string(peer.port);
|
|
||||||
std::string rpc_port = peer.rpc_port ? std::to_string(peer.rpc_port) : "-";
|
|
||||||
std::string pruning_seed = epee::string_tools::to_string_hex(peer.pruning_seed);
|
|
||||||
tools::msg_writer() << fmt::format("{:<10} {:<25} {:<25} {:<5} %{:-4} {}", prefix, id_str, addr_str, rpc_port, pruning_seed, elapsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_block_header(block_header_response const & header)
|
void print_block_header(block_header_response const & header)
|
||||||
{
|
{
|
||||||
tools::success_msg_writer()
|
tools::success_msg_writer()
|
||||||
|
@ -178,6 +160,36 @@ namespace {
|
||||||
std::string get_human_time_ago(std::time_t t, std::time_t now, bool abbreviate = false) {
|
std::string get_human_time_ago(std::time_t t, std::time_t now, bool abbreviate = false) {
|
||||||
return get_human_time_ago(std::chrono::seconds{now - t}, abbreviate);
|
return get_human_time_ago(std::chrono::seconds{now - t}, abbreviate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool print_peer(std::string_view prefix, const json& peer, bool pruned_only, bool publicrpc_only)
|
||||||
|
{
|
||||||
|
auto pruning_seed = peer.value<uint64_t>("pruning_seed", 0);
|
||||||
|
if (pruned_only && pruning_seed == 0)
|
||||||
|
return false;
|
||||||
|
auto rpc_port = peer.value<uint16_t>("rpc_port", 0);
|
||||||
|
if (publicrpc_only && rpc_port == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
time_t now = std::time(nullptr);
|
||||||
|
time_t last_seen = peer.value<time_t>("last_seen", 0);
|
||||||
|
|
||||||
|
tools::msg_writer() << fmt::format("{:<10} {:016x} {:<30} {:<5} {:<4x} {}",
|
||||||
|
prefix,
|
||||||
|
peer["id"].get<uint64_t>(),
|
||||||
|
fmt::format("{}:{}", peer["host"].get<std::string_view>(), peer["ip"].get<uint16_t>()),
|
||||||
|
rpc_port == 0 ? "-" : tools::int_to_string(rpc_port),
|
||||||
|
pruning_seed,
|
||||||
|
last_seen == 0 ? "never" : get_human_time_ago(last_seen, now));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
void print_peers(std::string_view prefix, const json& peers, size_t& limit, Args&&... args) {
|
||||||
|
for (auto it = peers.begin(); it != peers.end() && limit > 0; it++)
|
||||||
|
if (print_peer(prefix, *it, std::forward<Args>(args)...))
|
||||||
|
limit--;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc_command_executor::rpc_command_executor(
|
rpc_command_executor::rpc_command_executor(
|
||||||
|
@ -334,43 +346,35 @@ bool rpc_command_executor::print_sn_state_changes(uint64_t start_height, uint64_
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rpc_command_executor::print_peer_list(bool white, bool gray, size_t limit, bool pruned_only, bool publicrpc_only) {
|
bool rpc_command_executor::print_peer_list(bool white, bool gray, size_t limit, bool pruned_only, bool publicrpc_only) {
|
||||||
GET_PEER_LIST::response res{};
|
auto maybe_pl = try_running([this] { return invoke<GET_PEER_LIST>(); }, "Failed to retrieve peer list");
|
||||||
|
if (!maybe_pl)
|
||||||
if (!invoke<GET_PEER_LIST>({}, res, "Couldn't retrieve peer list"))
|
|
||||||
return false;
|
return false;
|
||||||
|
auto& pl = *maybe_pl;
|
||||||
|
|
||||||
if (white)
|
if (white)
|
||||||
{
|
print_peers("white", pl["white_list"], limit, pruned_only, publicrpc_only);
|
||||||
auto peer = res.white_list.cbegin();
|
|
||||||
const auto end = limit ? peer + std::min(limit, res.white_list.size()) : res.white_list.cend();
|
|
||||||
for (; peer != end; ++peer)
|
|
||||||
{
|
|
||||||
print_peer("white", *peer, pruned_only, publicrpc_only);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gray)
|
if (gray)
|
||||||
{
|
print_peers("gray", pl["gray_list"], limit, pruned_only, publicrpc_only);
|
||||||
auto peer = res.gray_list.cbegin();
|
|
||||||
const auto end = limit ? peer + std::min(limit, res.gray_list.size()) : res.gray_list.cend();
|
|
||||||
for (; peer != end; ++peer)
|
|
||||||
{
|
|
||||||
print_peer("gray", *peer, pruned_only, publicrpc_only);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rpc_command_executor::print_peer_list_stats() {
|
bool rpc_command_executor::print_peer_list_stats() {
|
||||||
GET_PEER_LIST::response res{};
|
auto maybe_info = try_running([this] { return invoke<GET_INFO>(); }, "Failed to retrieve node info");
|
||||||
|
if (!maybe_info)
|
||||||
if (!invoke<GET_PEER_LIST>({}, res, "Couldn't retrieve peer list"))
|
|
||||||
return false;
|
return false;
|
||||||
|
auto& info = *maybe_info;
|
||||||
|
|
||||||
|
auto wls = info.find("white_peerlist_size");
|
||||||
|
auto gls = info.find("grey_peerlist_size");
|
||||||
|
if (wls == info.end() || gls == info.end()) {
|
||||||
|
tools::fail_msg_writer() << "Failed to retrieve whitelist info";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
tools::msg_writer()
|
tools::msg_writer()
|
||||||
<< "White list size: " << res.white_list.size() << "/" << P2P_LOCAL_WHITE_PEERLIST_LIMIT << " (" << res.white_list.size() * 100.0 / P2P_LOCAL_WHITE_PEERLIST_LIMIT << "%)" << std::endl
|
<< "White list size: " << wls->get<int>() << "/" << P2P_LOCAL_WHITE_PEERLIST_LIMIT << " (" << wls->get<int>() * 100.0 / P2P_LOCAL_WHITE_PEERLIST_LIMIT << "%)\n"
|
||||||
<< "Gray list size: " << res.gray_list.size() << "/" << P2P_LOCAL_GRAY_PEERLIST_LIMIT << " (" << res.gray_list.size() * 100.0 / P2P_LOCAL_GRAY_PEERLIST_LIMIT << "%)";
|
<< "Gray list size: " << gls->get<int>() << "/" << P2P_LOCAL_GRAY_PEERLIST_LIMIT << " (" << gls->get<int>() * 100.0 / P2P_LOCAL_GRAY_PEERLIST_LIMIT << "%)";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,8 +260,6 @@ namespace cryptonote::rpc {
|
||||||
|
|
||||||
if (address.empty())
|
if (address.empty())
|
||||||
m_bootstrap_daemon.reset();
|
m_bootstrap_daemon.reset();
|
||||||
else if (address == "auto")
|
|
||||||
m_bootstrap_daemon = std::make_unique<bootstrap_daemon>([this]{ return get_random_public_node(); });
|
|
||||||
else
|
else
|
||||||
m_bootstrap_daemon = std::make_unique<bootstrap_daemon>(address, credentials);
|
m_bootstrap_daemon = std::make_unique<bootstrap_daemon>(address, credentials);
|
||||||
|
|
||||||
|
@ -270,46 +268,6 @@ namespace cryptonote::rpc {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
std::optional<std::string> core_rpc_server::get_random_public_node()
|
|
||||||
{
|
|
||||||
GET_PUBLIC_NODES::response response{};
|
|
||||||
try
|
|
||||||
{
|
|
||||||
GET_PUBLIC_NODES::request request{};
|
|
||||||
request.gray = true;
|
|
||||||
request.white = true;
|
|
||||||
|
|
||||||
rpc_context context = {};
|
|
||||||
context.admin = true;
|
|
||||||
response = invoke(std::move(request), context);
|
|
||||||
}
|
|
||||||
catch(const std::exception &e)
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto get_random_node_address = [](const std::vector<public_node>& public_nodes) -> std::string {
|
|
||||||
const auto& random_node = public_nodes[crypto::rand_idx(public_nodes.size())];
|
|
||||||
const auto address = random_node.host + ":" + std::to_string(random_node.rpc_port);
|
|
||||||
return address;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!response.white.empty())
|
|
||||||
{
|
|
||||||
return get_random_node_address(response.white);
|
|
||||||
}
|
|
||||||
|
|
||||||
MDEBUG("No white public node found, checking gray peers");
|
|
||||||
|
|
||||||
if (!response.gray.empty())
|
|
||||||
{
|
|
||||||
return get_random_node_address(response.gray);
|
|
||||||
}
|
|
||||||
|
|
||||||
MERROR("Failed to find any suitable public node");
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
void core_rpc_server::init(const boost::program_options::variables_map& vm)
|
void core_rpc_server::init(const boost::program_options::variables_map& vm)
|
||||||
{
|
{
|
||||||
if (!set_bootstrap_daemon(command_line::get_arg(vm, arg_bootstrap_daemon_address),
|
if (!set_bootstrap_daemon(command_line::get_arg(vm, arg_bootstrap_daemon_address),
|
||||||
|
@ -1397,81 +1355,35 @@ namespace cryptonote::rpc {
|
||||||
}
|
}
|
||||||
save_bc.response["status"] = STATUS_OK;
|
save_bc.response["status"] = STATUS_OK;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
GET_PEER_LIST::response core_rpc_server::invoke(GET_PEER_LIST::request&& req, rpc_context context)
|
|
||||||
{
|
|
||||||
GET_PEER_LIST::response res{};
|
|
||||||
|
|
||||||
PERF_TIMER(on_get_peer_list);
|
static nlohmann::json json_peer_info(const nodetool::peerlist_entry& peer) {
|
||||||
std::vector<nodetool::peerlist_entry> white_list;
|
auto addr_type = peer.adr.get_type_id();
|
||||||
std::vector<nodetool::peerlist_entry> gray_list;
|
nlohmann::json p{
|
||||||
|
{"id", peer.id},
|
||||||
if (req.public_only)
|
{"host", peer.adr.host_str()},
|
||||||
{
|
{"port", peer.adr.port()},
|
||||||
m_p2p.get_public_peerlist(gray_list, white_list);
|
{"last_seen", peer.last_seen}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_p2p.get_peerlist(gray_list, white_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto & entry : white_list)
|
|
||||||
{
|
|
||||||
if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id())
|
|
||||||
res.white_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv4_network_address>().ip(),
|
|
||||||
entry.adr.as<epee::net_utils::ipv4_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port);
|
|
||||||
else if (entry.adr.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id())
|
|
||||||
res.white_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv6_network_address>().host_str(),
|
|
||||||
entry.adr.as<epee::net_utils::ipv6_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port);
|
|
||||||
else
|
|
||||||
res.white_list.emplace_back(entry.id, entry.adr.str(), entry.last_seen, entry.pruning_seed, entry.rpc_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto & entry : gray_list)
|
|
||||||
{
|
|
||||||
if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id())
|
|
||||||
res.gray_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv4_network_address>().ip(),
|
|
||||||
entry.adr.as<epee::net_utils::ipv4_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port);
|
|
||||||
else if (entry.adr.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id())
|
|
||||||
res.gray_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv6_network_address>().host_str(),
|
|
||||||
entry.adr.as<epee::net_utils::ipv6_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port);
|
|
||||||
else
|
|
||||||
res.gray_list.emplace_back(entry.id, entry.adr.str(), entry.last_seen, entry.pruning_seed, entry.rpc_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
res.status = STATUS_OK;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
GET_PUBLIC_NODES::response core_rpc_server::invoke(GET_PUBLIC_NODES::request&& req, rpc_context context)
|
|
||||||
{
|
|
||||||
PERF_TIMER(on_get_public_nodes);
|
|
||||||
|
|
||||||
GET_PEER_LIST::response peer_list_res = invoke(GET_PEER_LIST::request{}, context);
|
|
||||||
GET_PUBLIC_NODES::response res{};
|
|
||||||
res.status = std::move(peer_list_res.status);
|
|
||||||
|
|
||||||
const auto collect = [](const std::vector<GET_PEER_LIST::peer> &peer_list, std::vector<public_node> &public_nodes)
|
|
||||||
{
|
|
||||||
for (const auto &entry : peer_list)
|
|
||||||
{
|
|
||||||
if (entry.rpc_port != 0)
|
|
||||||
{
|
|
||||||
public_nodes.emplace_back(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
if (peer.pruning_seed) p["pruning_seed"] = peer.pruning_seed;
|
||||||
|
if (peer.rpc_port) p["rpc_port"] = peer.rpc_port;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
if (req.white)
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
{
|
void core_rpc_server::invoke(GET_PEER_LIST& pl, rpc_context context)
|
||||||
collect(peer_list_res.white_list, res.white);
|
{
|
||||||
}
|
PERF_TIMER(on_get_peer_list);
|
||||||
if (req.gray)
|
std::vector<nodetool::peerlist_entry> white_list, gray_list;
|
||||||
{
|
|
||||||
collect(peer_list_res.gray_list, res.gray);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
if (pl.request.public_only)
|
||||||
|
m_p2p.get_public_peerlist(gray_list, white_list);
|
||||||
|
else
|
||||||
|
m_p2p.get_peerlist(gray_list, white_list);
|
||||||
|
|
||||||
|
std::transform(white_list.begin(), white_list.end(), std::back_inserter(pl.response["white_list"]), json_peer_info);
|
||||||
|
std::transform(gray_list.begin(), gray_list.end(), std::back_inserter(pl.response["gray_list"]), json_peer_info);
|
||||||
|
|
||||||
|
pl.response["status"] = STATUS_OK;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
SET_LOG_LEVEL::response core_rpc_server::invoke(SET_LOG_LEVEL::request&& req, rpc_context context)
|
SET_LOG_LEVEL::response core_rpc_server::invoke(SET_LOG_LEVEL::request&& req, rpc_context context)
|
||||||
|
|
|
@ -225,6 +225,7 @@ namespace cryptonote::rpc {
|
||||||
void invoke(IS_KEY_IMAGE_SPENT& spent, rpc_context context);
|
void invoke(IS_KEY_IMAGE_SPENT& spent, rpc_context context);
|
||||||
void invoke(SUBMIT_TRANSACTION& tx, rpc_context context);
|
void invoke(SUBMIT_TRANSACTION& tx, rpc_context context);
|
||||||
void invoke(GET_BLOCK_HASH& req, rpc_context context);
|
void invoke(GET_BLOCK_HASH& req, rpc_context context);
|
||||||
|
void invoke(GET_PEER_LIST& pl, rpc_context context);
|
||||||
|
|
||||||
// Deprecated Monero NIH binary endpoints:
|
// Deprecated Monero NIH binary endpoints:
|
||||||
GET_ALT_BLOCKS_HASHES_BIN::response invoke(GET_ALT_BLOCKS_HASHES_BIN::request&& req, rpc_context context);
|
GET_ALT_BLOCKS_HASHES_BIN::response invoke(GET_ALT_BLOCKS_HASHES_BIN::request&& req, rpc_context context);
|
||||||
|
@ -238,8 +239,6 @@ namespace cryptonote::rpc {
|
||||||
GET_TX_GLOBAL_OUTPUTS_INDEXES_BIN::response invoke(GET_TX_GLOBAL_OUTPUTS_INDEXES_BIN::request&& req, rpc_context context);
|
GET_TX_GLOBAL_OUTPUTS_INDEXES_BIN::response invoke(GET_TX_GLOBAL_OUTPUTS_INDEXES_BIN::request&& req, rpc_context context);
|
||||||
|
|
||||||
// FIXME: unconverted JSON RPC endpoints:
|
// FIXME: unconverted JSON RPC endpoints:
|
||||||
GET_PEER_LIST::response invoke(GET_PEER_LIST::request&& req, rpc_context context);
|
|
||||||
GET_PUBLIC_NODES::response invoke(GET_PUBLIC_NODES::request&& req, rpc_context context);
|
|
||||||
SET_LOG_LEVEL::response invoke(SET_LOG_LEVEL::request&& req, rpc_context context);
|
SET_LOG_LEVEL::response invoke(SET_LOG_LEVEL::request&& req, rpc_context context);
|
||||||
SET_LOG_CATEGORIES::response invoke(SET_LOG_CATEGORIES::request&& req, rpc_context context);
|
SET_LOG_CATEGORIES::response invoke(SET_LOG_CATEGORIES::request&& req, rpc_context context);
|
||||||
SET_BOOTSTRAP_DAEMON::response invoke(SET_BOOTSTRAP_DAEMON::request&& req, rpc_context context);
|
SET_BOOTSTRAP_DAEMON::response invoke(SET_BOOTSTRAP_DAEMON::request&& req, rpc_context context);
|
||||||
|
@ -293,7 +292,6 @@ private:
|
||||||
|
|
||||||
//utils
|
//utils
|
||||||
uint64_t get_block_reward(const block& blk);
|
uint64_t get_block_reward(const block& blk);
|
||||||
std::optional<std::string> get_random_public_node();
|
|
||||||
bool set_bootstrap_daemon(const std::string &address, std::string_view username_password);
|
bool set_bootstrap_daemon(const std::string &address, std::string_view username_password);
|
||||||
bool set_bootstrap_daemon(const std::string &address, std::string_view username, std::string_view password);
|
bool set_bootstrap_daemon(const std::string &address, std::string_view username, std::string_view password);
|
||||||
void fill_block_header_response(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_response& response, bool fill_pow_hash, bool get_tx_hashes);
|
void fill_block_header_response(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_response& response, bool fill_pow_hash, bool get_tx_hashes);
|
||||||
|
|
|
@ -393,4 +393,8 @@ namespace cryptonote::rpc {
|
||||||
if (bh.request.heights.size() > bh.MAX_HEIGHTS)
|
if (bh.request.heights.size() > bh.MAX_HEIGHTS)
|
||||||
throw std::domain_error{"Error: too many block heights requested at once"};
|
throw std::domain_error{"Error: too many block heights requested at once"};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parse_request(GET_PEER_LIST& pl, rpc_input in) {
|
||||||
|
get_values(in, "public_only", pl.request.public_only);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,4 +21,5 @@ namespace cryptonote::rpc {
|
||||||
void parse_request(IS_KEY_IMAGE_SPENT& spent, rpc_input in);
|
void parse_request(IS_KEY_IMAGE_SPENT& spent, rpc_input in);
|
||||||
void parse_request(SUBMIT_TRANSACTION& tx, rpc_input in);
|
void parse_request(SUBMIT_TRANSACTION& tx, rpc_input in);
|
||||||
void parse_request(GET_BLOCK_HASH& bh, rpc_input in);
|
void parse_request(GET_BLOCK_HASH& bh, rpc_input in);
|
||||||
|
void parse_request(GET_PEER_LIST& bh, rpc_input in);
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,44 +106,6 @@ KV_SERIALIZE_MAP_CODE_BEGIN(GET_BLOCK::response)
|
||||||
KV_SERIALIZE_MAP_CODE_END()
|
KV_SERIALIZE_MAP_CODE_END()
|
||||||
|
|
||||||
|
|
||||||
KV_SERIALIZE_MAP_CODE_BEGIN(GET_PEER_LIST::peer)
|
|
||||||
KV_SERIALIZE(id)
|
|
||||||
KV_SERIALIZE(host)
|
|
||||||
KV_SERIALIZE(ip)
|
|
||||||
KV_SERIALIZE(port)
|
|
||||||
KV_SERIALIZE_OPT(rpc_port, (uint16_t)0)
|
|
||||||
KV_SERIALIZE(last_seen)
|
|
||||||
KV_SERIALIZE_OPT(pruning_seed, (uint32_t)0)
|
|
||||||
KV_SERIALIZE_MAP_CODE_END()
|
|
||||||
|
|
||||||
KV_SERIALIZE_MAP_CODE_BEGIN(GET_PEER_LIST::request)
|
|
||||||
KV_SERIALIZE_OPT(public_only, true)
|
|
||||||
KV_SERIALIZE_MAP_CODE_END()
|
|
||||||
|
|
||||||
KV_SERIALIZE_MAP_CODE_BEGIN(GET_PEER_LIST::response)
|
|
||||||
KV_SERIALIZE(status)
|
|
||||||
KV_SERIALIZE(white_list)
|
|
||||||
KV_SERIALIZE(gray_list)
|
|
||||||
KV_SERIALIZE_MAP_CODE_END()
|
|
||||||
|
|
||||||
KV_SERIALIZE_MAP_CODE_BEGIN(public_node)
|
|
||||||
KV_SERIALIZE(host)
|
|
||||||
KV_SERIALIZE(last_seen)
|
|
||||||
KV_SERIALIZE(rpc_port)
|
|
||||||
KV_SERIALIZE_MAP_CODE_END()
|
|
||||||
|
|
||||||
KV_SERIALIZE_MAP_CODE_BEGIN(GET_PUBLIC_NODES::request)
|
|
||||||
KV_SERIALIZE_OPT(gray, false)
|
|
||||||
KV_SERIALIZE_OPT(white, true)
|
|
||||||
KV_SERIALIZE_MAP_CODE_END()
|
|
||||||
|
|
||||||
KV_SERIALIZE_MAP_CODE_BEGIN(GET_PUBLIC_NODES::response)
|
|
||||||
KV_SERIALIZE(status)
|
|
||||||
KV_SERIALIZE(gray)
|
|
||||||
KV_SERIALIZE(white)
|
|
||||||
KV_SERIALIZE_MAP_CODE_END()
|
|
||||||
|
|
||||||
|
|
||||||
KV_SERIALIZE_MAP_CODE_BEGIN(SET_LOG_LEVEL::request)
|
KV_SERIALIZE_MAP_CODE_BEGIN(SET_LOG_LEVEL::request)
|
||||||
KV_SERIALIZE(level)
|
KV_SERIALIZE(level)
|
||||||
KV_SERIALIZE_MAP_CODE_END()
|
KV_SERIALIZE_MAP_CODE_END()
|
||||||
|
|
|
@ -871,88 +871,34 @@ namespace cryptonote::rpc {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
OXEN_RPC_DOC_INTROSPECT
|
/// Get the list of current network peers known to this node.
|
||||||
// Get the known peers list.
|
///
|
||||||
|
/// Inputs: none
|
||||||
|
///
|
||||||
|
/// Output values (requires a restricted/admin RPC endpoint):
|
||||||
|
///
|
||||||
|
/// - \p status General RPC status string. `"OK"` means everything looks good.
|
||||||
|
/// - \p white_list list of "whitelist" peers (see below), that is, peers that were recorded
|
||||||
|
/// reachable the last time this node connected to them. Peers that are unreachable or not
|
||||||
|
/// synchronized with the network are moved to the graylist.
|
||||||
|
/// - \p gray_list list of peers (see below) that this node knows of but has not (recently) tried
|
||||||
|
/// to connect to.
|
||||||
|
///
|
||||||
|
/// Each peer list is an array of dicts containing the following fields:
|
||||||
|
/// - \p id a unique integer locally identifying the peer
|
||||||
|
/// - \p host the peer's IP address (as a string)
|
||||||
|
/// - \p port the port on which the peer is reachable
|
||||||
|
/// - \p last_seen unix timestamp when this node last connected to the peer. Will be omitted if
|
||||||
|
/// never connected (e.g. for a peer we received from another node but haven't yet tried).
|
||||||
struct GET_PEER_LIST : LEGACY
|
struct GET_PEER_LIST : LEGACY
|
||||||
{
|
{
|
||||||
static constexpr auto names() { return NAMES("get_peer_list"); }
|
static constexpr auto names() { return NAMES("get_peer_list"); }
|
||||||
|
|
||||||
struct request
|
struct request_parameters
|
||||||
{
|
{
|
||||||
bool public_only;
|
bool public_only = false; // Hidden option: can be set to false to also include non-public-zone peers (Tor, I2P), but since Oxen currently only really exists in public zones, we don't put this in the RPC docs.
|
||||||
KV_MAP_SERIALIZABLE
|
} request;
|
||||||
};
|
|
||||||
|
|
||||||
struct peer
|
|
||||||
{
|
|
||||||
uint64_t id; // Peer id.
|
|
||||||
std::string host; // IP address in string format.
|
|
||||||
uint32_t ip; // IP address in integer format.
|
|
||||||
uint16_t port; // TCP port the peer is using to connect to oxen network.
|
|
||||||
uint16_t rpc_port; // RPC port the peer is using
|
|
||||||
uint64_t last_seen; // Unix time at which the peer has been seen for the last time
|
|
||||||
uint32_t pruning_seed; //
|
|
||||||
|
|
||||||
peer() = default;
|
|
||||||
|
|
||||||
peer(uint64_t id, const std::string &host, uint64_t last_seen, uint32_t pruning_seed, uint16_t rpc_port)
|
|
||||||
: id(id), host(host), ip(0), port(0), rpc_port(rpc_port), last_seen(last_seen), pruning_seed(pruning_seed)
|
|
||||||
{}
|
|
||||||
peer(uint64_t id, const std::string &host, uint16_t port, uint64_t last_seen, uint32_t pruning_seed, uint16_t rpc_port)
|
|
||||||
: id(id), host(host), ip(0), port(port), rpc_port(rpc_port), last_seen(last_seen), pruning_seed(pruning_seed)
|
|
||||||
{}
|
|
||||||
peer(uint64_t id, uint32_t ip, uint16_t port, uint64_t last_seen, uint32_t pruning_seed, uint16_t rpc_port)
|
|
||||||
: id(id), host(epee::string_tools::get_ip_string_from_int32(ip)), ip(ip), port(port), rpc_port(rpc_port), last_seen(last_seen), pruning_seed(pruning_seed)
|
|
||||||
{}
|
|
||||||
|
|
||||||
KV_MAP_SERIALIZABLE
|
|
||||||
};
|
|
||||||
|
|
||||||
struct response
|
|
||||||
{
|
|
||||||
std::string status; // General RPC error code. "OK" means everything looks good. Any other value means that something went wrong.
|
|
||||||
std::vector<peer> white_list; // Array of online peer structure.
|
|
||||||
std::vector<peer> gray_list; // Array of offline peer structure.
|
|
||||||
|
|
||||||
KV_MAP_SERIALIZABLE
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
OXEN_RPC_DOC_INTROSPECT
|
|
||||||
struct public_node
|
|
||||||
{
|
|
||||||
std::string host;
|
|
||||||
uint64_t last_seen;
|
|
||||||
uint16_t rpc_port;
|
|
||||||
|
|
||||||
public_node() = default;
|
|
||||||
public_node(const GET_PEER_LIST::peer &peer) : host(peer.host), last_seen(peer.last_seen), rpc_port(peer.rpc_port) {}
|
|
||||||
|
|
||||||
KV_MAP_SERIALIZABLE
|
|
||||||
};
|
|
||||||
|
|
||||||
OXEN_RPC_DOC_INTROSPECT
|
|
||||||
// Query the daemon's peerlist and retrieve peers who have set their public rpc port.
|
|
||||||
struct GET_PUBLIC_NODES : PUBLIC
|
|
||||||
{
|
|
||||||
static constexpr auto names() { return NAMES("get_public_nodes"); }
|
|
||||||
|
|
||||||
struct request
|
|
||||||
{
|
|
||||||
bool gray; // Get peers that have recently gone offline.
|
|
||||||
bool white; // Get peers that are online
|
|
||||||
|
|
||||||
KV_MAP_SERIALIZABLE
|
|
||||||
};
|
|
||||||
|
|
||||||
struct response
|
|
||||||
{
|
|
||||||
std::string status; // General RPC error code. "OK" means everything looks good. Any other value means that something went wrong.
|
|
||||||
std::vector<public_node> gray; // Graylist peers
|
|
||||||
std::vector<public_node> white; // Whitelist peers
|
|
||||||
|
|
||||||
KV_MAP_SERIALIZABLE
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
OXEN_RPC_DOC_INTROSPECT
|
OXEN_RPC_DOC_INTROSPECT
|
||||||
|
@ -2432,7 +2378,8 @@ namespace cryptonote::rpc {
|
||||||
GET_SERVICE_NODES,
|
GET_SERVICE_NODES,
|
||||||
GET_SERVICE_NODE_STATUS,
|
GET_SERVICE_NODE_STATUS,
|
||||||
SUBMIT_TRANSACTION,
|
SUBMIT_TRANSACTION,
|
||||||
GET_BLOCK_HASH
|
GET_BLOCK_HASH,
|
||||||
|
GET_PEER_LIST
|
||||||
>;
|
>;
|
||||||
|
|
||||||
using FIXME_old_rpc_types = tools::type_list<
|
using FIXME_old_rpc_types = tools::type_list<
|
||||||
|
@ -2441,8 +2388,6 @@ namespace cryptonote::rpc {
|
||||||
GET_BLOCK_HEADER_BY_HASH,
|
GET_BLOCK_HEADER_BY_HASH,
|
||||||
GET_BLOCK_HEADER_BY_HEIGHT,
|
GET_BLOCK_HEADER_BY_HEIGHT,
|
||||||
GET_BLOCK,
|
GET_BLOCK,
|
||||||
GET_PEER_LIST,
|
|
||||||
GET_PUBLIC_NODES,
|
|
||||||
SET_LOG_LEVEL,
|
SET_LOG_LEVEL,
|
||||||
SET_LOG_CATEGORIES,
|
SET_LOG_CATEGORIES,
|
||||||
GET_BLOCK_HEADERS_RANGE,
|
GET_BLOCK_HEADERS_RANGE,
|
||||||
|
|
Loading…
Reference in a new issue