mirror of
https://github.com/oxen-io/oxen-core.git
synced 2023-12-14 02:22:56 +01:00
Add storage server reachability field; test it with quorums (#820)
* Add storage server reachability field; test it with quorums * Improve method names * Address review comments
This commit is contained in:
parent
add6051a8f
commit
b91e690a62
|
@ -2169,6 +2169,11 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::set_storage_server_peer_reachable(crypto::public_key const &pubkey, bool value)
|
||||
{
|
||||
return m_service_node_list.set_storage_server_peer_reachable(pubkey, value);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::update_blockchain_pruning()
|
||||
{
|
||||
return m_blockchain_storage.update_blockchain_pruning();
|
||||
|
|
|
@ -887,6 +887,11 @@ namespace cryptonote
|
|||
*/
|
||||
void record_checkpoint_vote(crypto::public_key const &pubkey, bool voted) { m_service_node_list.record_checkpoint_vote(pubkey, voted); }
|
||||
|
||||
/**
|
||||
* @brief Record the reachability status of node's storage server
|
||||
*/
|
||||
bool set_storage_server_peer_reachable(crypto::public_key const &pubkey, bool value);
|
||||
|
||||
/// Time point at which the storage server last pinged us
|
||||
std::atomic<time_t> m_last_storage_server_ping;
|
||||
private:
|
||||
|
|
|
@ -1814,6 +1814,26 @@ namespace service_nodes
|
|||
info.vote_index = (info.vote_index + 1) % info.votes.size();
|
||||
}
|
||||
|
||||
bool service_node_list::set_storage_server_peer_reachable(crypto::public_key const &pubkey, bool value)
|
||||
{
|
||||
std::lock_guard<boost::recursive_mutex> lock(m_sn_mutex);
|
||||
|
||||
auto it = m_state.service_nodes_infos.find(pubkey);
|
||||
if (it == m_state.service_nodes_infos.end()) {
|
||||
LOG_PRINT_L2("No Service Node is known by this pubkey: " << pubkey);
|
||||
return false;
|
||||
} else {
|
||||
|
||||
proof_info &info = *it->second->proof;
|
||||
if (info.storage_server_reachable != value) {
|
||||
info.storage_server_reachable = value;
|
||||
LOG_PRINT_L2("Setting reachability status for node " << pubkey << " as: " << (value ? "true" : "false"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static quorum_manager quorum_for_serialization_to_quorum_manager(service_node_list::quorum_for_serialization const &source)
|
||||
{
|
||||
quorum_manager result = {};
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace service_nodes
|
|||
std::array<bool, CHECKPOINT_MIN_QUORUMS_NODE_MUST_VOTE_IN_BEFORE_DEREGISTER_CHECK> votes;
|
||||
uint8_t vote_index = 0;
|
||||
std::array<std::pair<uint32_t, uint64_t>, 2> public_ips = {}; // (not serialized)
|
||||
bool storage_server_reachable = true;
|
||||
proof_info() { votes.fill(true); }
|
||||
|
||||
// Called to update both actual and effective timestamp, i.e. when a proof is received
|
||||
|
@ -260,6 +261,8 @@ namespace service_nodes
|
|||
bool handle_uptime_proof (cryptonote::NOTIFY_UPTIME_PROOF::request const &proof);
|
||||
void record_checkpoint_vote (crypto::public_key const &pubkey, bool voted);
|
||||
|
||||
bool set_storage_server_peer_reachable(crypto::public_key const &pubkey, bool value);
|
||||
|
||||
struct quorum_for_serialization
|
||||
{
|
||||
uint8_t version;
|
||||
|
|
|
@ -82,6 +82,11 @@ namespace service_nodes
|
|||
result.uptime_proved = false;
|
||||
}
|
||||
|
||||
if (!info.proof->storage_server_reachable) {
|
||||
LOG_PRINT_L1("Service Node is not reachable for node: " << pubkey);
|
||||
result.storage_server_reachable = false;
|
||||
}
|
||||
|
||||
// IP change checks
|
||||
const auto &ips = proof.public_ips;
|
||||
if (ips[0].first && ips[1].first) {
|
||||
|
@ -282,6 +287,18 @@ namespace service_nodes
|
|||
passed = true;
|
||||
}
|
||||
|
||||
|
||||
if (test_results.uptime_proved && !test_results.storage_server_reachable &&
|
||||
m_core.get_nettype() == cryptonote::MAINNET &&
|
||||
m_obligations_height < HF_VERSION_12_CHECKPOINTING_SOFT_FORK_HEIGHT)
|
||||
{
|
||||
LOG_PRINT_L1("HF12 Checkpointing Pre-Soft Fork: Service node: "
|
||||
<< node_key
|
||||
<< " has unreachable storage server, it would have entered the "
|
||||
"decommission phase");
|
||||
passed = true;
|
||||
}
|
||||
|
||||
new_state vote_for_state;
|
||||
if (passed) {
|
||||
if (info.is_decommissioned()) {
|
||||
|
|
|
@ -65,11 +65,12 @@ namespace service_nodes
|
|||
};
|
||||
|
||||
struct service_node_test_results {
|
||||
bool uptime_proved = true;
|
||||
bool single_ip = true;
|
||||
bool voted_in_checkpoints = true;
|
||||
bool uptime_proved = true;
|
||||
bool single_ip = true;
|
||||
bool voted_in_checkpoints = true;
|
||||
bool storage_server_reachable = true;
|
||||
|
||||
bool passed() const { return uptime_proved && voted_in_checkpoints; }
|
||||
bool passed() const { return uptime_proved && voted_in_checkpoints && storage_server_reachable; }
|
||||
};
|
||||
|
||||
class quorum_cop
|
||||
|
|
|
@ -2740,6 +2740,7 @@ namespace cryptonote
|
|||
entry.service_node_version = {info.proof->version_major, info.proof->version_minor, info.proof->version_patch};
|
||||
entry.public_ip = string_tools::get_ip_string_from_int32(info.proof->public_ip);
|
||||
entry.storage_port = info.proof->storage_port;
|
||||
entry.storage_server_reachable = info.proof->storage_server_reachable;
|
||||
|
||||
entry.contributors.reserve(info.contributors.size());
|
||||
|
||||
|
@ -3142,6 +3143,35 @@ namespace cryptonote
|
|||
res.status = CORE_RPC_STATUS_OK;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_report_peer_storage_server_status(const COMMAND_RPC_REPORT_PEER_SS_STATUS::request& req,
|
||||
COMMAND_RPC_REPORT_PEER_SS_STATUS::response& res,
|
||||
epee::json_rpc::error& error_resp,
|
||||
const connection_context* ctx)
|
||||
{
|
||||
crypto::public_key pubkey;
|
||||
if (!string_tools::hex_to_pod(req.pubkey, pubkey)) {
|
||||
MERROR("Could not parse public key: " << req.pubkey);
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
|
||||
error_resp.message = "Could not parse public key";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (req.type == "reachability") {
|
||||
|
||||
if (!m_core.set_storage_server_peer_reachable(pubkey, req.passed)) {
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
|
||||
error_resp.message = "Pubkey not found";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
|
||||
error_resp.message = "Unknown status type";
|
||||
return false;
|
||||
}
|
||||
|
||||
res.status = CORE_RPC_STATUS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace cryptonote
|
||||
|
|
|
@ -184,10 +184,11 @@ namespace cryptonote
|
|||
MAP_JON_RPC_WE("get_all_service_nodes_keys", on_get_all_service_nodes_keys, COMMAND_RPC_GET_ALL_SERVICE_NODES_KEYS)
|
||||
MAP_JON_RPC_WE("get_n_service_nodes", on_get_n_service_nodes, COMMAND_RPC_GET_N_SERVICE_NODES)
|
||||
MAP_JON_RPC_WE("get_staking_requirement", on_get_staking_requirement, COMMAND_RPC_GET_STAKING_REQUIREMENT)
|
||||
MAP_JON_RPC_WE("get_checkpoints", on_get_checkpoints, COMMAND_RPC_GET_CHECKPOINTS)
|
||||
MAP_JON_RPC_WE("get_checkpoints", on_get_checkpoints, COMMAND_RPC_GET_CHECKPOINTS)
|
||||
MAP_JON_RPC_WE_IF("perform_blockchain_test", on_perform_blockchain_test, COMMAND_RPC_PERFORM_BLOCKCHAIN_TEST, !m_restricted)
|
||||
MAP_JON_RPC_WE_IF("storage_server_ping", on_storage_server_ping, COMMAND_RPC_STORAGE_SERVER_PING, !m_restricted)
|
||||
MAP_JON_RPC_WE("get_service_nodes_state_changes", on_get_service_nodes_state_changes, COMMAND_RPC_GET_SN_STATE_CHANGES)
|
||||
MAP_JON_RPC_WE_IF("report_peer_storage_server_status", on_report_peer_storage_server_status, COMMAND_RPC_REPORT_PEER_SS_STATUS, !m_restricted)
|
||||
END_JSON_RPC_MAP()
|
||||
END_URI_MAP2()
|
||||
|
||||
|
@ -277,6 +278,7 @@ namespace cryptonote
|
|||
bool on_storage_server_ping(const COMMAND_RPC_STORAGE_SERVER_PING::request& req, COMMAND_RPC_STORAGE_SERVER_PING::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
bool on_get_checkpoints(const COMMAND_RPC_GET_CHECKPOINTS::request& req, COMMAND_RPC_GET_CHECKPOINTS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
bool on_get_service_nodes_state_changes(const COMMAND_RPC_GET_SN_STATE_CHANGES::request& req, COMMAND_RPC_GET_SN_STATE_CHANGES::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
bool on_report_peer_storage_server_status(const COMMAND_RPC_REPORT_PEER_SS_STATUS::request& req, COMMAND_RPC_REPORT_PEER_SS_STATUS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
//-----------------------
|
||||
|
||||
#if defined(LOKI_ENABLE_INTEGRATION_TEST_HOOKS)
|
||||
|
|
|
@ -2763,6 +2763,7 @@ namespace cryptonote
|
|||
std::string operator_address; // The wallet address of the operator to which the operator cut of the staking reward is sent to.
|
||||
std::string public_ip; // The public ip address of the service node
|
||||
uint16_t storage_port; // The port number associated with the storage server
|
||||
bool storage_server_reachable; // Whether the node's storage server has been reported as unreachable for a long time
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(service_node_pubkey)
|
||||
|
@ -2786,6 +2787,7 @@ namespace cryptonote
|
|||
KV_SERIALIZE(operator_address)
|
||||
KV_SERIALIZE(public_ip)
|
||||
KV_SERIALIZE(storage_port)
|
||||
KV_SERIALIZE(storage_server_reachable)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
@ -2843,6 +2845,7 @@ namespace cryptonote
|
|||
bool operator_address;
|
||||
bool public_ip;
|
||||
bool storage_port;
|
||||
bool storage_server_reachable;
|
||||
|
||||
bool block_hash;
|
||||
bool height;
|
||||
|
@ -2871,6 +2874,7 @@ namespace cryptonote
|
|||
KV_SERIALIZE_OPT2(operator_address, false)
|
||||
KV_SERIALIZE_OPT2(public_ip, false)
|
||||
KV_SERIALIZE_OPT2(storage_port, false)
|
||||
KV_SERIALIZE_OPT2(storage_server_reachable, false)
|
||||
KV_SERIALIZE_OPT2(block_hash, false)
|
||||
KV_SERIALIZE_OPT2(height, false)
|
||||
KV_SERIALIZE_OPT2(target_height, false)
|
||||
|
@ -2923,6 +2927,7 @@ namespace cryptonote
|
|||
std::string operator_address; // The wallet address of the operator to which the operator cut of the staking reward is sent to.
|
||||
std::string public_ip; // The public ip address of the service node
|
||||
uint16_t storage_port; // The port number associated with the storage server
|
||||
bool storage_server_reachable; // Whether the node's storage server has been reported as unreachable for a long time
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_ENTRY_FIELD_IF_REQUESTED(service_node_pubkey);
|
||||
|
@ -2946,6 +2951,7 @@ namespace cryptonote
|
|||
KV_SERIALIZE_ENTRY_FIELD_IF_REQUESTED(operator_address);
|
||||
KV_SERIALIZE_ENTRY_FIELD_IF_REQUESTED(public_ip);
|
||||
KV_SERIALIZE_ENTRY_FIELD_IF_REQUESTED(storage_port);
|
||||
KV_SERIALIZE_ENTRY_FIELD_IF_REQUESTED(storage_server_reachable);
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
@ -3233,4 +3239,30 @@ namespace cryptonote
|
|||
};
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
|
||||
|
||||
LOKI_RPC_DOC_INTROSPECT
|
||||
struct COMMAND_RPC_REPORT_PEER_SS_STATUS
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string type; // test type (currently used: ["reachability"])
|
||||
std::string pubkey; // service node pubkey
|
||||
bool passed; // whether the node is passing the test
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(type)
|
||||
KV_SERIALIZE(pubkey)
|
||||
KV_SERIALIZE(passed)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string status; // Generic RPC error code. "OK" is the success value.
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue