Service Nodes Improve Reliability & Feedback (#262)

* If unable to receive own uptime proof, switch to more granular pinging

* Uptime proof simpler solution to repeatedly ping on failure
This commit is contained in:
Doyle 2018-09-27 18:31:08 +10:00 committed by GitHub
parent 8fc283dac0
commit a71b7640d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 14 deletions

View file

@ -63,7 +63,7 @@ static_assert(STAKING_PORTIONS % 3 == 0, "Use a multiple of three, so that it di
#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW 11
#define UPTIME_PROOF_BUFFER_IN_SECONDS (5*60)
#define UPTIME_PROOF_BUFFER_IN_SECONDS (5*60) // The acceptable window of time to accept a peer's uptime proof from its reported timestamp
#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)

View file

@ -411,6 +411,7 @@ namespace cryptonote
{
r = init_service_node_key();
CHECK_AND_ASSERT_MES(r, false, "Failed to create or load service node key");
m_service_node_list.set_my_service_node_keys(&m_service_node_pubkey);
}
boost::filesystem::path folder(m_config_folder);
@ -1103,7 +1104,10 @@ namespace cryptonote
cryptonote_connection_context fake_context = AUTO_VAL_INIT(fake_context);
NOTIFY_UPTIME_PROOF::request r;
m_quorum_cop.generate_uptime_proof_request(m_service_node_pubkey, m_service_node_key, r);
get_protocol()->relay_uptime_proof(r, fake_context);
bool relayed = get_protocol()->relay_uptime_proof(r, fake_context);
if (relayed)
MGINFO("Submitted uptime-proof for service node (yours): " << m_service_node_pubkey);
}
return true;
}
@ -1444,17 +1448,23 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
void core::do_uptime_proof_call()
{
std::vector<service_nodes::service_node_pubkey_info> states = get_service_node_list_state({ m_service_node_pubkey });
// wait one block before starting uptime proofs.
std::vector<service_nodes::service_node_pubkey_info> const states = get_service_node_list_state({ m_service_node_pubkey });
if (!states.empty() && states[0].info.registration_height + 1 < get_current_blockchain_height())
{
m_submit_uptime_proof_interval.do_call(boost::bind(&core::submit_uptime_proof, this));
// 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);
if (last_uptime <= static_cast<uint64_t>(time(nullptr) - UPTIME_PROOF_FREQUENCY_IN_SECONDS))
this->submit_uptime_proof();
return true;
});
}
else
{
// reset the interval so that we're ready when we register.
m_submit_uptime_proof_interval = epee::math_helper::once_a_time_seconds<UPTIME_PROOF_FREQUENCY_IN_SECONDS, true>();
// reset the interval so that we're ready when we register, OR if we get deregistered this primes us up for re-registration in the same session
m_check_uptime_proof_interval = epee::math_helper::once_a_time_seconds<UPTIME_PROOF_BUFFER_IN_SECONDS, true /*start_immediately*/>();
}
}
//-----------------------------------------------------------------------------------------------
@ -1484,8 +1494,13 @@ namespace cryptonote
m_deregisters_auto_relayer.do_call(boost::bind(&core::relay_deregister_votes, this));
m_check_updates_interval.do_call(boost::bind(&core::check_updates, this));
m_check_disk_space_interval.do_call(boost::bind(&core::check_disk_space, this));
if (m_service_node)
time_t const lifetime = time(nullptr) - get_start_time();
if (m_service_node && lifetime > DIFFICULTY_TARGET_V2) // Give us some time to connect to peers before sending uptimes
{
do_uptime_proof_call();
}
m_uptime_proof_pruner.do_call(boost::bind(&service_nodes::quorum_cop::prune_uptime_proof, &m_quorum_cop));
m_miner.on_idle();

View file

@ -1056,7 +1056,7 @@ namespace cryptonote
epee::math_helper::once_a_time_seconds<60*2, false> m_deregisters_auto_relayer; //!< interval for checking re-relaying deregister votes
epee::math_helper::once_a_time_seconds<60*60*12, true> m_check_updates_interval; //!< interval for checking for new versions
epee::math_helper::once_a_time_seconds<60*10, true> m_check_disk_space_interval; //!< interval for checking for disk space
epee::math_helper::once_a_time_seconds<UPTIME_PROOF_FREQUENCY_IN_SECONDS, true> m_submit_uptime_proof_interval; //!< interval for submitting uptime proof
epee::math_helper::once_a_time_seconds<UPTIME_PROOF_BUFFER_IN_SECONDS, true> m_check_uptime_proof_interval; //!< interval for checking our own uptime proof
epee::math_helper::once_a_time_seconds<30, true> m_uptime_proof_pruner;
std::atomic<bool> m_starter_message_showed; //!< has the "daemon will sync now" message been shown?

View file

@ -49,7 +49,7 @@ namespace service_nodes
{
service_node_list::service_node_list(cryptonote::Blockchain& blockchain)
: m_blockchain(blockchain), m_hooks_registered(false), m_height(0), m_db(nullptr)
: m_blockchain(blockchain), m_hooks_registered(false), m_height(0), m_db(nullptr), m_service_node_pubkey(nullptr)
{
}
@ -280,7 +280,15 @@ namespace service_nodes
if (iter == m_service_nodes_infos.end())
return;
LOG_PRINT_L1("Deregistration for service node: " << key);
if (m_service_node_pubkey && *m_service_node_pubkey == key)
{
MGINFO_RED("Deregistration for service node (yours): " << key);
}
else
{
LOG_PRINT_L1("Deregistration for service node: " << key);
}
m_rollback_events.push_back(std::unique_ptr<rollback_event>(new rollback_change(block_height, key, iter->second)));
m_service_nodes_infos.erase(iter);
@ -386,7 +394,14 @@ namespace service_nodes
if (iter != m_service_nodes_infos.end())
return;
LOG_PRINT_L1("New service node registered: " << key << " at block height: " << block_height);
if (m_service_node_pubkey && *m_service_node_pubkey == key)
{
MGINFO_GREEN("New service node registered (yours): " << key << " at block height: " << block_height);
}
else
{
LOG_PRINT_L1("New service node registered: " << key << " at block height: " << block_height);
}
m_rollback_events.push_back(std::unique_ptr<rollback_event>(new rollback_new(block_height, key)));
m_service_nodes_infos[key] = info;
@ -984,8 +999,8 @@ namespace service_nodes
}
}
LOG_PRINT_L0("Service node data loaded successfully, m_height: " << m_height);
LOG_PRINT_L0(m_service_nodes_infos.size() << " nodes and " << m_rollback_events.size() << " rollback events loaded.");
MGINFO("Service node data loaded successfully, m_height: " << m_height);
MGINFO(m_service_nodes_infos.size() << " nodes and " << m_rollback_events.size() << " rollback events loaded.");
LOG_PRINT_L1("service_node_list::load() returning success");
return true;

View file

@ -138,6 +138,7 @@ namespace service_nodes
std::vector<service_node_pubkey_info> get_service_node_list_state(const std::vector<crypto::public_key> &service_node_pubkeys) const;
void set_db_pointer(cryptonote::BlockchainDB* db) { m_db = db; }
void set_my_service_node_keys(crypto::public_key const *pub_key) { m_service_node_pubkey = pub_key; }
bool store();
bool is_registration_tx(const cryptonote::transaction& tx, uint64_t block_timestamp, uint64_t block_height, uint32_t index, crypto::public_key& key, service_node_info& info) const;
@ -275,6 +276,8 @@ namespace service_nodes
bool m_hooks_registered;
block_height m_height;
crypto::public_key const *m_service_node_pubkey;
cryptonote::BlockchainDB* m_db;
std::map<block_height, std::shared_ptr<quorum_state>> m_quorum_states;