Require storage server running for uptime proofs (v.2) (#631)

* Require storage server running for uptime proofs (v.2)

* use atomic time_t; reset ping on startup
This commit is contained in:
Maxim Shishmarev 2019-06-07 17:03:11 +10:00 committed by Doyle
parent ae76293487
commit e53922faa8
6 changed files with 78 additions and 1 deletions

View file

@ -34,6 +34,7 @@
#include <string>
#include <boost/uuid/uuid.hpp>
#include <stdexcept>
#include <chrono>
#define CRYPTONOTE_DNS_TIMEOUT_MS 20000
@ -66,6 +67,8 @@ static_assert(STAKING_PORTIONS % 3 == 0, "Use a multiple of three, so that it di
#define UPTIME_PROOF_FREQUENCY_IN_SECONDS (60*60)
#define UPTIME_PROOF_MAX_TIME_IN_SECONDS (UPTIME_PROOF_FREQUENCY_IN_SECONDS * 2 + UPTIME_PROOF_BUFFER_IN_SECONDS)
#define STORAGE_SERVER_PING_LIFETIME UPTIME_PROOF_FREQUENCY_IN_SECONDS
// MONEY_SUPPLY - total number coins to be generated
#define MONEY_SUPPLY ((uint64_t)(-1))
#define EMISSION_SPEED_FACTOR_PER_MINUTE (20)

View file

@ -238,6 +238,10 @@ namespace cryptonote
{
m_checkpoints_updating.clear();
set_cryptonote_protocol(pprotocol);
// Reset the storage server last ping to make
// sure the very first uptime proof works
this->update_storage_server_last_ping();
}
void core::set_cryptonote_protocol(i_cryptonote_protocol* pprotocol)
{
@ -1404,6 +1408,26 @@ namespace cryptonote
return res;
}
//-----------------------------------------------------------------------------------------------
bool core::check_storage_server_ping() const
{
time_t last_ping = m_last_storage_server_ping.load();
const auto elapsed = std::time(nullptr) - last_ping;
if (elapsed > STORAGE_SERVER_PING_LIFETIME) {
MWARNING("Have not heard from the storage server since at least: "
<< epee::misc_utils::get_time_str(last_ping));
return false;
}
return true;
}
//-----------------------------------------------------------------------------------------------
void core::update_storage_server_last_ping()
{
m_last_storage_server_ping.store(std::time(nullptr));
}
//-----------------------------------------------------------------------------------------------
void core::on_transaction_relayed(const cryptonote::blobdata& tx_blob)
{
std::vector<std::pair<crypto::hash, cryptonote::blobdata>> txs;
@ -1780,8 +1804,17 @@ namespace cryptonote
// Code snippet from Github @Jagerman
m_check_uptime_proof_interval.do_call([&states, this](){
uint64_t last_uptime = m_quorum_cop.get_uptime_proof(states[0].pubkey).timestamp;
if (last_uptime <= static_cast<uint64_t>(time(nullptr) - UPTIME_PROOF_FREQUENCY_IN_SECONDS))
if (last_uptime <= static_cast<uint64_t>(time(nullptr) - UPTIME_PROOF_FREQUENCY_IN_SECONDS)) {
if (!this->check_storage_server_ping()) {
MERROR("Failed to submit uptime proof: have not heard from"
<< " the storage server recently. "
<< "Make sure that it is running!");
return true;
}
this->submit_uptime_proof();
}
return true;
});

View file

@ -861,6 +861,18 @@ namespace cryptonote
*/
service_nodes::proof_info get_uptime_proof(const crypto::public_key &key) const;
/**
* @brief Check if the ping last recieved from the storage server has expired
*
* @return true if it has not expired
*/
bool check_storage_server_ping() const;
/**
* @brief Update the storage server ping time
*/
void update_storage_server_last_ping();
/*
* @brief get the blockchain pruning seed
*
@ -1140,6 +1152,9 @@ namespace cryptonote
uint32_t m_sn_public_ip;
uint16_t m_storage_port;
/// Time point at which the storage server last pinged us
std::atomic<time_t> m_last_storage_server_ping;
size_t block_sync_size;
time_t start_time;

View file

@ -2884,6 +2884,15 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_storage_server_ping(const COMMAND_RPC_STORAGE_SERVER_PING::request&,
COMMAND_RPC_STORAGE_SERVER_PING::response&,
epee::json_rpc::error&,
const connection_context*)
{
m_core.update_storage_server_last_ping();
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_staking_requirement(const COMMAND_RPC_GET_STAKING_REQUIREMENT::request& req, COMMAND_RPC_GET_STAKING_REQUIREMENT::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
PERF_TIMER(on_get_staking_requirement);

View file

@ -186,6 +186,7 @@ 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_staking_requirement", on_get_staking_requirement, COMMAND_RPC_GET_STAKING_REQUIREMENT)
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)
END_JSON_RPC_MAP()
END_URI_MAP2()
@ -273,6 +274,7 @@ namespace cryptonote
bool on_get_staking_requirement(const COMMAND_RPC_GET_STAKING_REQUIREMENT::request& req, COMMAND_RPC_GET_STAKING_REQUIREMENT::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
/// Provide a proof that this node holds the blockchain
bool on_perform_blockchain_test(const COMMAND_RPC_PERFORM_BLOCKCHAIN_TEST::request& req, COMMAND_RPC_PERFORM_BLOCKCHAIN_TEST::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
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);
//-----------------------
void on_get_checkpoints() { m_core.debug__print_checkpoints(); }

View file

@ -2826,6 +2826,21 @@ namespace cryptonote
typedef epee::misc_utils::struct_init<response_t> response;
};
struct COMMAND_RPC_STORAGE_SERVER_PING
{
struct request
{
BEGIN_KV_SERIALIZE_MAP()
END_KV_SERIALIZE_MAP()
};
struct response
{
BEGIN_KV_SERIALIZE_MAP()
END_KV_SERIALIZE_MAP()
};
};
LOKI_RPC_DOC_INTROSPECT
// Get the required amount of Loki to become a Service Node at the queried height.
// For stagenet and testnet values, ensure the daemon is started with the