mirror of
https://github.com/oxen-io/oxen-core.git
synced 2023-12-14 02:22:56 +01:00
Merge pull request #1422 from jagerman/uptime-proof-tweaks
Tweak uptime proof times; reduce times for testnet
This commit is contained in:
commit
d164e1a41e
10 changed files with 121 additions and 87 deletions
|
@ -897,11 +897,6 @@ if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND ARCH_WIDTH EQUAL "32" AND NOT IOS AN
|
|||
endif()
|
||||
endif()
|
||||
|
||||
option(OXEN_DEBUG_SHORT_PROOFS "Developer option to substantially reduce uptime proof intervals for local test network debugging (the result oxend will not be usable on the live networks)" OFF)
|
||||
if (OXEN_DEBUG_SHORT_PROOFS)
|
||||
add_definitions(-DUPTIME_PROOF_BASE_MINUTE=3) # 20x faster uptime proofs
|
||||
endif()
|
||||
|
||||
|
||||
if(BUILD_STATIC_DEPS)
|
||||
# sqlite3 target already set up
|
||||
|
|
|
@ -29,9 +29,6 @@
|
|||
#ifndef OXEN_H
|
||||
#define OXEN_H
|
||||
|
||||
#define OXEN_HOUR(val) ((val) * OXEN_MINUTES(60))
|
||||
#define OXEN_MINUTES(val) val * 60
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
|
|
|
@ -61,20 +61,6 @@ static_assert(STAKING_PORTIONS % 12 == 0, "Use a multiple of twelve, so that it
|
|||
|
||||
#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW 11
|
||||
|
||||
// For local testnet debug purposes allow shrinking the uptime proof frequency
|
||||
#ifndef UPTIME_PROOF_BASE_MINUTE
|
||||
#define UPTIME_PROOF_BASE_MINUTE 60
|
||||
#endif
|
||||
|
||||
#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_INITIAL_DELAY_SECONDS (2*UPTIME_PROOF_BASE_MINUTE) // Delay after startup before sending a proof (to allow connections to be established)
|
||||
#define UPTIME_PROOF_TIMER_SECONDS (5*UPTIME_PROOF_BASE_MINUTE) // How often we check whether we need to send an uptime proof
|
||||
#define UPTIME_PROOF_FREQUENCY_IN_SECONDS (60*UPTIME_PROOF_BASE_MINUTE) // How often we resend uptime proofs normally (i.e. after we've seen an uptime proof reply from the network)
|
||||
#define UPTIME_PROOF_MAX_TIME_IN_SECONDS (UPTIME_PROOF_FREQUENCY_IN_SECONDS * 2 + UPTIME_PROOF_BUFFER_IN_SECONDS) // How long until proofs of other network service nodes are considered expired
|
||||
|
||||
#define STORAGE_SERVER_PING_LIFETIME UPTIME_PROOF_FREQUENCY_IN_SECONDS
|
||||
#define LOKINET_PING_LIFETIME UPTIME_PROOF_FREQUENCY_IN_SECONDS
|
||||
|
||||
#define CRYPTONOTE_REWARD_BLOCKS_WINDOW 100
|
||||
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 20000 // NOTE(oxen): For testing suite, //size of block (bytes) after which reward for block calculated using block size - before first fork
|
||||
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 300000 //size of block (bytes) after which reward for block calculated using block size - second change, from v5
|
||||
|
@ -250,6 +236,12 @@ namespace config
|
|||
"LDBEN6Ut4NkMwyaXWZ7kBEAx8X64o6YtDhLXUP26uLHyYT4nFmcaPU2Z2fauqrhTLh4Qfr61pUUZVLaTHqAdycETKM1STrz"sv, // hardfork v11
|
||||
};
|
||||
|
||||
inline constexpr auto UPTIME_PROOF_TOLERANCE = 5min; // How much an uptime proof timestamp can deviate from our timestamp before we refuse it
|
||||
inline constexpr auto UPTIME_PROOF_STARTUP_DELAY = 30s; // How long to wait after startup before broadcasting a proof
|
||||
inline constexpr auto UPTIME_PROOF_CHECK_INTERVAL = 30s; // How frequently to check whether we need to broadcast a proof
|
||||
inline constexpr auto UPTIME_PROOF_FREQUENCY = 1h; // How often to send proofs out to the network since the last proof we successfully sent. (Approximately; this can be up to CHECK_INTERFACE/2 off in either direction). The minimum accepted time between proofs is half of this.
|
||||
inline constexpr auto UPTIME_PROOF_VALIDITY = 2h + 5min; // The maximum time that we consider an uptime proof to be valid (i.e. after this time since the last proof we consider the SN to be down)
|
||||
|
||||
// Hash domain separators
|
||||
inline constexpr std::string_view HASH_KEY_BULLETPROOF_EXPONENT = "bulletproof"sv;
|
||||
inline constexpr std::string_view HASH_KEY_RINGDB = "ringdsb\0"sv;
|
||||
|
@ -288,6 +280,9 @@ namespace config
|
|||
"T6TzkJb5EiASaCkcH7idBEi1HSrpSQJE1Zq3aL65ojBMPZvqHNYPTL56i3dncGVNEYCG5QG5zrBmRiVwcg6b1cRM1SRNqbp44"sv, // hardfork v10
|
||||
};
|
||||
|
||||
// Testnet uptime proofs are 6x faster than mainnet (devnet config also uses these)
|
||||
inline constexpr auto UPTIME_PROOF_FREQUENCY = 10min;
|
||||
inline constexpr auto UPTIME_PROOF_VALIDITY = 21min;
|
||||
}
|
||||
|
||||
namespace devnet
|
||||
|
@ -314,6 +309,15 @@ namespace config
|
|||
"dV3EhSE1xXgSzswBgVioqFNTfcqGopvTrcYjs4YDLHUfU64DuHxFoEmbwoyipTidGiTXx5EuYdgzZhDLMTo9uEv82M4A7Uimp"sv, // hardfork v10
|
||||
};
|
||||
}
|
||||
|
||||
namespace fakechain {
|
||||
// Fakechain uptime proofs are 60x faster than mainnet, because this really only runs on a
|
||||
// hand-crafted, typically local temporary network.
|
||||
inline constexpr auto UPTIME_PROOF_STARTUP_DELAY = 5s;
|
||||
inline constexpr auto UPTIME_PROOF_CHECK_INTERVAL = 5s;
|
||||
inline constexpr auto UPTIME_PROOF_FREQUENCY = 1min;
|
||||
inline constexpr auto UPTIME_PROOF_VALIDITY = 2min + 5s;
|
||||
}
|
||||
}
|
||||
|
||||
namespace cryptonote
|
||||
|
@ -376,6 +380,12 @@ namespace cryptonote
|
|||
uint64_t GOVERNANCE_REWARD_INTERVAL_IN_BLOCKS;
|
||||
std::array<std::string_view, 2> GOVERNANCE_WALLET_ADDRESS;
|
||||
|
||||
std::chrono::seconds UPTIME_PROOF_TOLERANCE;
|
||||
std::chrono::seconds UPTIME_PROOF_STARTUP_DELAY;
|
||||
std::chrono::seconds UPTIME_PROOF_CHECK_INTERVAL;
|
||||
std::chrono::seconds UPTIME_PROOF_FREQUENCY;
|
||||
std::chrono::seconds UPTIME_PROOF_VALIDITY;
|
||||
|
||||
inline constexpr std::string_view governance_wallet_address(int hard_fork_version) const {
|
||||
const auto wallet_switch =
|
||||
(NETWORK_TYPE == MAINNET || NETWORK_TYPE == FAKECHAIN)
|
||||
|
@ -384,7 +394,7 @@ namespace cryptonote
|
|||
return GOVERNANCE_WALLET_ADDRESS[hard_fork_version >= wallet_switch ? 1 : 0];
|
||||
}
|
||||
};
|
||||
inline constexpr network_config mainnet_config = {
|
||||
inline constexpr network_config mainnet_config{
|
||||
MAINNET,
|
||||
::config::HEIGHT_ESTIMATE_HEIGHT,
|
||||
::config::HEIGHT_ESTIMATE_TIMESTAMP,
|
||||
|
@ -400,8 +410,13 @@ namespace cryptonote
|
|||
::config::GENESIS_NONCE,
|
||||
::config::GOVERNANCE_REWARD_INTERVAL_IN_BLOCKS,
|
||||
::config::GOVERNANCE_WALLET_ADDRESS,
|
||||
config::UPTIME_PROOF_TOLERANCE,
|
||||
config::UPTIME_PROOF_STARTUP_DELAY,
|
||||
config::UPTIME_PROOF_CHECK_INTERVAL,
|
||||
config::UPTIME_PROOF_FREQUENCY,
|
||||
config::UPTIME_PROOF_VALIDITY,
|
||||
};
|
||||
inline constexpr network_config testnet_config = {
|
||||
inline constexpr network_config testnet_config{
|
||||
TESTNET,
|
||||
::config::testnet::HEIGHT_ESTIMATE_HEIGHT,
|
||||
::config::testnet::HEIGHT_ESTIMATE_TIMESTAMP,
|
||||
|
@ -417,8 +432,13 @@ namespace cryptonote
|
|||
::config::testnet::GENESIS_NONCE,
|
||||
::config::testnet::GOVERNANCE_REWARD_INTERVAL_IN_BLOCKS,
|
||||
::config::testnet::GOVERNANCE_WALLET_ADDRESS,
|
||||
config::UPTIME_PROOF_TOLERANCE,
|
||||
config::UPTIME_PROOF_STARTUP_DELAY,
|
||||
config::UPTIME_PROOF_CHECK_INTERVAL,
|
||||
config::testnet::UPTIME_PROOF_FREQUENCY,
|
||||
config::testnet::UPTIME_PROOF_VALIDITY,
|
||||
};
|
||||
inline constexpr network_config devnet_config = {
|
||||
inline constexpr network_config devnet_config{
|
||||
DEVNET,
|
||||
::config::devnet::HEIGHT_ESTIMATE_HEIGHT,
|
||||
::config::devnet::HEIGHT_ESTIMATE_TIMESTAMP,
|
||||
|
@ -434,8 +454,13 @@ namespace cryptonote
|
|||
::config::devnet::GENESIS_NONCE,
|
||||
::config::devnet::GOVERNANCE_REWARD_INTERVAL_IN_BLOCKS,
|
||||
::config::devnet::GOVERNANCE_WALLET_ADDRESS,
|
||||
config::UPTIME_PROOF_TOLERANCE,
|
||||
config::UPTIME_PROOF_STARTUP_DELAY,
|
||||
config::UPTIME_PROOF_CHECK_INTERVAL,
|
||||
config::testnet::UPTIME_PROOF_FREQUENCY,
|
||||
config::testnet::UPTIME_PROOF_VALIDITY,
|
||||
};
|
||||
inline constexpr network_config fakenet_config = {
|
||||
inline constexpr network_config fakenet_config{
|
||||
FAKECHAIN,
|
||||
::config::HEIGHT_ESTIMATE_HEIGHT,
|
||||
::config::HEIGHT_ESTIMATE_TIMESTAMP,
|
||||
|
@ -451,6 +476,11 @@ namespace cryptonote
|
|||
::config::GENESIS_NONCE,
|
||||
100, //::config::GOVERNANCE_REWARD_INTERVAL_IN_BLOCKS,
|
||||
::config::GOVERNANCE_WALLET_ADDRESS,
|
||||
config::UPTIME_PROOF_TOLERANCE,
|
||||
config::fakechain::UPTIME_PROOF_STARTUP_DELAY,
|
||||
config::fakechain::UPTIME_PROOF_CHECK_INTERVAL,
|
||||
config::fakechain::UPTIME_PROOF_FREQUENCY,
|
||||
config::fakechain::UPTIME_PROOF_VALIDITY,
|
||||
};
|
||||
|
||||
inline constexpr const network_config& get_config(network_type nettype)
|
||||
|
|
|
@ -376,6 +376,7 @@ namespace cryptonote
|
|||
const bool devnet = command_line::get_arg(vm, arg_devnet_on);
|
||||
m_nettype = testnet ? TESTNET : devnet ? DEVNET : MAINNET;
|
||||
}
|
||||
m_check_uptime_proof_interval.interval(get_net_config().UPTIME_PROOF_CHECK_INTERVAL);
|
||||
|
||||
m_config_folder = fs::u8path(command_line::get_arg(vm, arg_data_dir));
|
||||
|
||||
|
@ -2276,14 +2277,14 @@ namespace cryptonote
|
|||
return m_blockchain_storage.get_block_by_height(height, blk);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
static bool check_external_ping(time_t last_ping, time_t lifetime, const char *what)
|
||||
static bool check_external_ping(time_t last_ping, std::chrono::seconds lifetime, std::string_view what)
|
||||
{
|
||||
const auto elapsed = std::time(nullptr) - last_ping;
|
||||
const std::chrono::seconds elapsed{std::time(nullptr) - last_ping};
|
||||
if (elapsed > lifetime)
|
||||
{
|
||||
MWARNING("Have not heard from " << what << " " <<
|
||||
(!last_ping ? "since starting" :
|
||||
"for more than " + tools::get_human_readable_timespan(std::chrono::seconds(elapsed))));
|
||||
"since more than " + tools::get_human_readable_timespan(elapsed) + " ago"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -2303,10 +2304,12 @@ namespace cryptonote
|
|||
m_check_uptime_proof_interval.do_call([this]() {
|
||||
// This timer is not perfectly precise and can leak seconds slightly, so send the uptime
|
||||
// proof if we are within half a tick of the target time. (Essentially our target proof
|
||||
// window becomes the first time this triggers in the 57.5-62.5 minute window).
|
||||
// window becomes the first time this triggers in the 59.75-60.25 minute window).
|
||||
uint64_t next_proof_time = 0;
|
||||
m_service_node_list.access_proof(m_service_keys.pub, [&](auto &proof) { next_proof_time = proof.timestamp; });
|
||||
next_proof_time += UPTIME_PROOF_FREQUENCY_IN_SECONDS - UPTIME_PROOF_TIMER_SECONDS/2;
|
||||
auto& netconf = get_net_config();
|
||||
next_proof_time += std::chrono::seconds{
|
||||
netconf.UPTIME_PROOF_FREQUENCY - netconf.UPTIME_PROOF_CHECK_INTERVAL/2}.count();
|
||||
|
||||
if ((uint64_t) std::time(nullptr) < next_proof_time)
|
||||
return;
|
||||
|
@ -2341,14 +2344,14 @@ namespace cryptonote
|
|||
|
||||
if (m_nettype != DEVNET)
|
||||
{
|
||||
if (!check_external_ping(m_last_storage_server_ping, STORAGE_SERVER_PING_LIFETIME, "the storage server"))
|
||||
if (!check_external_ping(m_last_storage_server_ping, get_net_config().UPTIME_PROOF_FREQUENCY, "the storage server"))
|
||||
{
|
||||
MGINFO_RED(
|
||||
"Failed to submit uptime proof: have not heard from the storage server recently. Make sure that it "
|
||||
"is running! It is required to run alongside the Loki daemon");
|
||||
return;
|
||||
}
|
||||
if (!check_external_ping(m_last_lokinet_ping, LOKINET_PING_LIFETIME, "Lokinet"))
|
||||
if (!check_external_ping(m_last_lokinet_ping, get_net_config().UPTIME_PROOF_FREQUENCY, "Lokinet"))
|
||||
{
|
||||
MGINFO_RED(
|
||||
"Failed to submit uptime proof: have not heard from lokinet recently. Make sure that it "
|
||||
|
@ -2395,9 +2398,8 @@ namespace cryptonote
|
|||
m_block_rate_interval.do_call([this] { return check_block_rate(); });
|
||||
m_sn_proof_cleanup_interval.do_call([&snl=m_service_node_list] { snl.cleanup_proofs(); return true; });
|
||||
|
||||
time_t const lifetime = time(nullptr) - get_start_time();
|
||||
int proof_delay = m_nettype == FAKECHAIN ? 5 : UPTIME_PROOF_INITIAL_DELAY_SECONDS;
|
||||
if (m_service_node && lifetime > proof_delay) // Give us some time to connect to peers before sending uptimes
|
||||
std::chrono::seconds lifetime{time(nullptr) - get_start_time()};
|
||||
if (m_service_node && lifetime > get_net_config().UPTIME_PROOF_STARTUP_DELAY) // Give us some time to connect to peers before sending uptimes
|
||||
{
|
||||
do_uptime_proof_call();
|
||||
}
|
||||
|
|
|
@ -851,6 +851,11 @@ namespace cryptonote
|
|||
*/
|
||||
network_type get_nettype() const { return m_nettype; };
|
||||
|
||||
/**
|
||||
* Returns the config settings for the network we are on.
|
||||
*/
|
||||
constexpr const network_config& get_net_config() const { return get_config(m_nettype); }
|
||||
|
||||
/**
|
||||
* @brief get whether transaction relay should be padded
|
||||
*
|
||||
|
@ -1218,7 +1223,7 @@ namespace cryptonote
|
|||
tools::periodic_task m_fork_moaner{2h}; //!< interval for checking HardFork status
|
||||
tools::periodic_task m_txpool_auto_relayer{2min, false}; //!< interval for checking re-relaying txpool transactions
|
||||
tools::periodic_task m_check_disk_space_interval{10min}; //!< interval for checking for disk space
|
||||
tools::periodic_task m_check_uptime_proof_interval{std::chrono::seconds{UPTIME_PROOF_TIMER_SECONDS}}; //!< interval for checking our own uptime proof
|
||||
tools::periodic_task m_check_uptime_proof_interval{30s}; //!< interval for checking our own uptime proof (will be set to get_net_config().UPTIME_PROOF_CHECK_INTERVAL after init)
|
||||
tools::periodic_task m_block_rate_interval{90s, false}; //!< interval for checking block rate
|
||||
tools::periodic_task m_blockchain_pruning_interval{5h}; //!< interval for incremental blockchain pruning
|
||||
tools::periodic_task m_service_node_vote_relayer{2min, false};
|
||||
|
|
|
@ -69,9 +69,9 @@ namespace service_nodes
|
|||
{
|
||||
size_t constexpr STORE_LONG_TERM_STATE_INTERVAL = 10000;
|
||||
|
||||
constexpr int X25519_MAP_PRUNING_INTERVAL = 5*60;
|
||||
constexpr int X25519_MAP_PRUNING_LAG = 24*60*60;
|
||||
static_assert(X25519_MAP_PRUNING_LAG > UPTIME_PROOF_MAX_TIME_IN_SECONDS, "x25519 map pruning lag is too short!");
|
||||
constexpr auto X25519_MAP_PRUNING_INTERVAL = 5min;
|
||||
constexpr auto X25519_MAP_PRUNING_LAG = 24h;
|
||||
static_assert(X25519_MAP_PRUNING_LAG > config::UPTIME_PROOF_VALIDITY, "x25519 map pruning lag is too short!");
|
||||
|
||||
static uint64_t short_term_state_cull_height(uint8_t hf_version, uint64_t block_height)
|
||||
{
|
||||
|
@ -2906,10 +2906,12 @@ namespace service_nodes
|
|||
bool service_node_list::handle_uptime_proof(cryptonote::NOTIFY_UPTIME_PROOF::request const &proof, bool &my_uptime_proof_confirmation, crypto::x25519_public_key &x25519_pkey)
|
||||
{
|
||||
uint8_t const hf_version = m_blockchain.get_current_hard_fork_version();
|
||||
uint64_t const now = time(nullptr);
|
||||
auto& netconf = get_config(m_blockchain.nettype());
|
||||
auto now = std::chrono::system_clock::now();
|
||||
|
||||
// Validate proof version, timestamp range,
|
||||
if ((proof.timestamp < now - UPTIME_PROOF_BUFFER_IN_SECONDS) || (proof.timestamp > now + UPTIME_PROOF_BUFFER_IN_SECONDS))
|
||||
auto time_deviation = now - std::chrono::system_clock::from_time_t(proof.timestamp);
|
||||
if (time_deviation > netconf.UPTIME_PROOF_TOLERANCE || time_deviation < -netconf.UPTIME_PROOF_TOLERANCE)
|
||||
REJECT_PROOF("timestamp is too far from now");
|
||||
|
||||
for (auto const &min : MIN_UPTIME_PROOF_VERSIONS)
|
||||
|
@ -2950,7 +2952,7 @@ namespace service_nodes
|
|||
auto &iproof = proofs[proof.pubkey];
|
||||
|
||||
|
||||
if (iproof.timestamp >= now - (UPTIME_PROOF_FREQUENCY_IN_SECONDS / 2))
|
||||
if (now <= std::chrono::system_clock::from_time_t(iproof.timestamp) + std::chrono::seconds{netconf.UPTIME_PROOF_FREQUENCY} / 2)
|
||||
REJECT_PROOF("already received one uptime proof for this node recently");
|
||||
|
||||
if (m_service_node_keys && proof.pubkey == m_service_node_keys->pub)
|
||||
|
@ -2969,13 +2971,13 @@ namespace service_nodes
|
|||
}
|
||||
|
||||
auto old_x25519 = iproof.pubkey_x25519;
|
||||
if (iproof.update(now, proof.public_ip, proof.storage_port, proof.storage_lmq_port, proof.qnet_port, proof.snode_version, proof.pubkey_ed25519, derived_x25519_pubkey))
|
||||
if (iproof.update(std::chrono::system_clock::to_time_t(now), proof.public_ip, proof.storage_port, proof.storage_lmq_port, proof.qnet_port, proof.snode_version, proof.pubkey_ed25519, derived_x25519_pubkey))
|
||||
iproof.store(proof.pubkey, m_blockchain);
|
||||
|
||||
if ((uint64_t) x25519_map_last_pruned + X25519_MAP_PRUNING_INTERVAL <= now)
|
||||
if (now - x25519_map_last_pruned >= X25519_MAP_PRUNING_INTERVAL)
|
||||
{
|
||||
time_t cutoff = now - X25519_MAP_PRUNING_LAG;
|
||||
erase_if(x25519_to_pub, [&cutoff](const decltype(x25519_to_pub)::value_type &x) { return x.second.second < cutoff; });
|
||||
time_t cutoff = std::chrono::system_clock::to_time_t(now - X25519_MAP_PRUNING_LAG);
|
||||
erase_if(x25519_to_pub, [&cutoff](auto &x) { return x.second.second < cutoff; });
|
||||
x25519_map_last_pruned = now;
|
||||
}
|
||||
|
||||
|
@ -2983,7 +2985,7 @@ namespace service_nodes
|
|||
x25519_to_pub.erase(old_x25519);
|
||||
|
||||
if (derived_x25519_pubkey)
|
||||
x25519_to_pub[derived_x25519_pubkey] = {proof.pubkey, now};
|
||||
x25519_to_pub[derived_x25519_pubkey] = {proof.pubkey, std::chrono::system_clock::to_time_t(now)};
|
||||
|
||||
if (derived_x25519_pubkey && (old_x25519 != derived_x25519_pubkey))
|
||||
x25519_pkey = derived_x25519_pubkey;
|
||||
|
@ -2997,10 +2999,12 @@ namespace service_nodes
|
|||
bool service_node_list::handle_btencoded_uptime_proof(std::unique_ptr<uptime_proof::Proof> proof, bool &my_uptime_proof_confirmation, crypto::x25519_public_key &x25519_pkey)
|
||||
{
|
||||
uint8_t const hf_version = m_blockchain.get_current_hard_fork_version();
|
||||
uint64_t const now = time(nullptr);
|
||||
auto& netconf = get_config(m_blockchain.nettype());
|
||||
auto now = std::chrono::system_clock::now();
|
||||
|
||||
// Validate proof version, timestamp range,
|
||||
if ((proof->timestamp < now - UPTIME_PROOF_BUFFER_IN_SECONDS) || (proof->timestamp > now + UPTIME_PROOF_BUFFER_IN_SECONDS))
|
||||
auto time_deviation = now - std::chrono::system_clock::from_time_t(proof->timestamp);
|
||||
if (time_deviation > netconf.UPTIME_PROOF_TOLERANCE || time_deviation < -netconf.UPTIME_PROOF_TOLERANCE)
|
||||
REJECT_PROOF("timestamp is too far from now");
|
||||
|
||||
for (auto const &min : MIN_UPTIME_PROOF_VERSIONS)
|
||||
|
@ -3039,7 +3043,7 @@ namespace service_nodes
|
|||
|
||||
auto &iproof = proofs[proof->pubkey];
|
||||
|
||||
if (iproof.timestamp >= now - (UPTIME_PROOF_FREQUENCY_IN_SECONDS / 2))
|
||||
if (now <= std::chrono::system_clock::from_time_t(iproof.timestamp) + std::chrono::seconds{netconf.UPTIME_PROOF_FREQUENCY} / 2)
|
||||
REJECT_PROOF("already received one uptime proof for this node recently");
|
||||
|
||||
if (m_service_node_keys && proof->pubkey == m_service_node_keys->pub)
|
||||
|
@ -3058,14 +3062,14 @@ namespace service_nodes
|
|||
}
|
||||
|
||||
auto old_x25519 = iproof.pubkey_x25519;
|
||||
if (iproof.update(now, std::move(proof), derived_x25519_pubkey))
|
||||
if (iproof.update(std::chrono::system_clock::to_time_t(now), std::move(proof), derived_x25519_pubkey))
|
||||
{
|
||||
iproof.store(iproof.proof->pubkey, m_blockchain);
|
||||
}
|
||||
|
||||
if ((uint64_t) x25519_map_last_pruned + X25519_MAP_PRUNING_INTERVAL <= now)
|
||||
if (now - x25519_map_last_pruned >= X25519_MAP_PRUNING_INTERVAL)
|
||||
{
|
||||
time_t cutoff = now - X25519_MAP_PRUNING_LAG;
|
||||
time_t cutoff = std::chrono::system_clock::to_time_t(now - X25519_MAP_PRUNING_LAG);
|
||||
erase_if(x25519_to_pub, [&cutoff](const decltype(x25519_to_pub)::value_type &x) { return x.second.second < cutoff; });
|
||||
x25519_map_last_pruned = now;
|
||||
}
|
||||
|
@ -3074,7 +3078,7 @@ namespace service_nodes
|
|||
x25519_to_pub.erase(old_x25519);
|
||||
|
||||
if (derived_x25519_pubkey)
|
||||
x25519_to_pub[derived_x25519_pubkey] = {iproof.proof->pubkey, now};
|
||||
x25519_to_pub[derived_x25519_pubkey] = {iproof.proof->pubkey, std::chrono::system_clock::to_time_t(now)};
|
||||
|
||||
if (derived_x25519_pubkey && (old_x25519 != derived_x25519_pubkey))
|
||||
x25519_pkey = derived_x25519_pubkey;
|
||||
|
|
|
@ -672,7 +672,7 @@ namespace service_nodes
|
|||
|
||||
/// Maps x25519 pubkeys to registration pubkeys + last block seen value (used for expiry)
|
||||
std::unordered_map<crypto::x25519_public_key, std::pair<crypto::public_key, time_t>> x25519_to_pub;
|
||||
time_t x25519_map_last_pruned = 0;
|
||||
std::chrono::system_clock::time_point x25519_map_last_pruned = std::chrono::system_clock::from_time_t(0);
|
||||
std::unordered_map<crypto::public_key, proof_info> proofs;
|
||||
|
||||
struct quorums_by_height
|
||||
|
|
|
@ -84,6 +84,8 @@ namespace service_nodes
|
|||
// has submitted uptime proofs, participated in required quorums, etc.
|
||||
service_node_test_results quorum_cop::check_service_node(uint8_t hf_version, const crypto::public_key &pubkey, const service_node_info &info) const
|
||||
{
|
||||
const auto& netconf = m_core.get_net_config();
|
||||
|
||||
service_node_test_results result; // Defaults to true for individual tests
|
||||
bool ss_reachable = true;
|
||||
uint64_t timestamp = 0;
|
||||
|
@ -112,7 +114,7 @@ namespace service_nodes
|
|||
}
|
||||
|
||||
});
|
||||
uint64_t time_since_last_uptime_proof = std::time(nullptr) - timestamp;
|
||||
std::chrono::seconds time_since_last_uptime_proof{std::time(nullptr) - timestamp};
|
||||
|
||||
bool check_uptime_obligation = true;
|
||||
bool check_checkpoint_obligation = true;
|
||||
|
@ -122,12 +124,12 @@ namespace service_nodes
|
|||
if (integration_test::state.disable_obligation_checkpointing) check_checkpoint_obligation = false;
|
||||
#endif
|
||||
|
||||
if (check_uptime_obligation && time_since_last_uptime_proof > UPTIME_PROOF_MAX_TIME_IN_SECONDS)
|
||||
if (check_uptime_obligation && time_since_last_uptime_proof > netconf.UPTIME_PROOF_VALIDITY)
|
||||
{
|
||||
LOG_PRINT_L1(
|
||||
"Service Node: " << pubkey << ", failed uptime proof obligation check: the last uptime proof was older than: "
|
||||
<< UPTIME_PROOF_MAX_TIME_IN_SECONDS << "s. Time since last uptime proof was: "
|
||||
<< tools::get_human_readable_timespan(std::chrono::seconds(time_since_last_uptime_proof)));
|
||||
"Service Node: " << pubkey << ", failed uptime proof obligation check: the last uptime proof (" <<
|
||||
tools::get_human_readable_timespan(time_since_last_uptime_proof) << ") was older than max validity (" <<
|
||||
tools::get_human_readable_timespan(netconf.UPTIME_PROOF_VALIDITY) << ")");
|
||||
result.uptime_proved = false;
|
||||
}
|
||||
|
||||
|
@ -145,8 +147,8 @@ namespace service_nodes
|
|||
std::vector<cryptonote::block> blocks;
|
||||
if (m_core.get_blocks(info.last_ip_change_height, 1, blocks)) {
|
||||
uint64_t find_ips_used_since = std::max(
|
||||
uint64_t(std::time(nullptr)) - IP_CHANGE_WINDOW_IN_SECONDS,
|
||||
uint64_t(blocks[0].timestamp) + IP_CHANGE_BUFFER_IN_SECONDS);
|
||||
uint64_t(std::time(nullptr)) - std::chrono::seconds{IP_CHANGE_WINDOW}.count(),
|
||||
uint64_t(blocks[0].timestamp) + std::chrono::seconds{IP_CHANGE_BUFFER}.count());
|
||||
if (ips[0].second > find_ips_used_since && ips[1].second > find_ips_used_since)
|
||||
result.single_ip = false;
|
||||
}
|
||||
|
@ -242,6 +244,8 @@ namespace service_nodes
|
|||
if (hf_version < cryptonote::network_version_9_service_nodes)
|
||||
return;
|
||||
|
||||
const auto& netconf = m_core.get_net_config();
|
||||
|
||||
uint64_t const REORG_SAFETY_BUFFER_BLOCKS = (hf_version >= cryptonote::network_version_12_checkpointing)
|
||||
? REORG_SAFETY_BUFFER_BLOCKS_POST_HF12
|
||||
: REORG_SAFETY_BUFFER_BLOCKS_PRE_HF12;
|
||||
|
@ -260,9 +264,8 @@ namespace service_nodes
|
|||
service_nodes::quorum_type const max_quorum_type = service_nodes::max_quorum_type_for_hf(hf_version);
|
||||
bool tested_myself_once_per_block = false;
|
||||
|
||||
time_t start_time = m_core.get_start_time();
|
||||
time_t const now = time(nullptr);
|
||||
int const live_time = (now - start_time);
|
||||
time_t start_time = m_core.get_start_time();
|
||||
std::chrono::seconds live_time{time(nullptr) - start_time};
|
||||
for (int i = 0; i <= (int)max_quorum_type; i++)
|
||||
{
|
||||
quorum_type const type = static_cast<quorum_type>(i);
|
||||
|
@ -317,22 +320,16 @@ namespace service_nodes
|
|||
}
|
||||
}
|
||||
|
||||
// NOTE: Wait at least 2 hours before we're allowed to vote so that we collect necessary voting information from people on the network
|
||||
bool alive_for_min_time = live_time >= MIN_TIME_IN_S_BEFORE_VOTING;
|
||||
if (!alive_for_min_time)
|
||||
#ifndef OXEN_ENABLE_INTEGRATION_TEST_HOOKS
|
||||
// NOTE: Wait at least 2 hours before we're allowed to vote so that we collect necessary
|
||||
// voting information from people on the network
|
||||
if (live_time < m_core.get_net_config().UPTIME_PROOF_VALIDITY)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
if (!m_core.service_node())
|
||||
continue;
|
||||
|
||||
if (m_core.get_nettype() == cryptonote::MAINNET && m_core.get_current_blockchain_height() < 646151)
|
||||
{
|
||||
// TODO(oxen): Pulse grace period, temporary code to be deleted
|
||||
// once the grace height has transpired to give Service Nodes time
|
||||
// to upgrade for the Pulse sorting key hot fix.
|
||||
continue;
|
||||
}
|
||||
|
||||
auto quorum = m_core.get_quorum(quorum_type::obligations, m_obligations_height);
|
||||
if (!quorum)
|
||||
{
|
||||
|
@ -448,8 +445,8 @@ namespace service_nodes
|
|||
// NOTE: Don't warn uptime proofs if the daemon is just
|
||||
// recently started and is candidate for testing (i.e.
|
||||
// restarting the daemon)
|
||||
if (!my_test_results.uptime_proved && live_time < OXEN_HOUR(1))
|
||||
continue;
|
||||
if (!my_test_results.uptime_proved && live_time < 1h)
|
||||
continue;
|
||||
|
||||
LOG_PRINT_L0("Service Node (yours) is active but is not passing tests for quorum: " << m_obligations_height);
|
||||
LOG_PRINT_L0(my_test_results.why());
|
||||
|
|
|
@ -156,7 +156,6 @@ namespace service_nodes {
|
|||
#if defined(OXEN_ENABLE_INTEGRATION_TEST_HOOKS)
|
||||
constexpr size_t STATE_CHANGE_QUORUM_SIZE = 5;
|
||||
constexpr size_t STATE_CHANGE_MIN_VOTES_TO_CHANGE_STATE = 1;
|
||||
constexpr int MIN_TIME_IN_S_BEFORE_VOTING = 0;
|
||||
constexpr size_t CHECKPOINT_QUORUM_SIZE = 5;
|
||||
constexpr size_t CHECKPOINT_MIN_VOTES = 1;
|
||||
constexpr int BLINK_SUBQUORUM_SIZE = 5;
|
||||
|
@ -164,7 +163,6 @@ namespace service_nodes {
|
|||
#else
|
||||
constexpr size_t STATE_CHANGE_MIN_VOTES_TO_CHANGE_STATE = 7;
|
||||
constexpr size_t STATE_CHANGE_QUORUM_SIZE = 10;
|
||||
constexpr int MIN_TIME_IN_S_BEFORE_VOTING = UPTIME_PROOF_MAX_TIME_IN_SECONDS;
|
||||
constexpr size_t CHECKPOINT_QUORUM_SIZE = 20;
|
||||
constexpr size_t CHECKPOINT_MIN_VOTES = 13;
|
||||
constexpr int BLINK_SUBQUORUM_SIZE = 10;
|
||||
|
@ -184,8 +182,8 @@ namespace service_nodes {
|
|||
static_assert(REORG_SAFETY_BUFFER_BLOCKS_POST_HF12 < VOTE_LIFETIME, "Safety buffer should always be less than the vote lifetime");
|
||||
static_assert(REORG_SAFETY_BUFFER_BLOCKS_PRE_HF12 < VOTE_LIFETIME, "Safety buffer should always be less than the vote lifetime");
|
||||
|
||||
constexpr uint64_t IP_CHANGE_WINDOW_IN_SECONDS = 24*60*60; // How far back an obligations quorum looks for multiple IPs (unless the following buffer is more recent)
|
||||
constexpr uint64_t IP_CHANGE_BUFFER_IN_SECONDS = 2*60*60; // After we bump a SN for an IP change we don't bump again for changes within this time period
|
||||
constexpr auto IP_CHANGE_WINDOW = 24h; // How far back an obligations quorum looks for multiple IPs (unless the following buffer is more recent)
|
||||
constexpr auto IP_CHANGE_BUFFER = 2h; // After we bump a SN for an IP change we don't bump again for changes within this time period
|
||||
|
||||
constexpr size_t MAX_SWARM_SIZE = 10;
|
||||
// We never create a new swarm unless there are SWARM_BUFFER extra nodes
|
||||
|
|
|
@ -3278,7 +3278,13 @@ namespace cryptonote { namespace rpc {
|
|||
// argument: true if this ping should trigger an immediate proof send (i.e. first ping after
|
||||
// startup or after a ping expiry), false for an ordinary ping.
|
||||
template <typename RPC, typename Success>
|
||||
auto handle_ping(std::array<uint16_t, 3> cur_version, std::array<uint16_t, 3> required, const char* name, std::atomic<std::time_t>& update, time_t lifetime, Success success)
|
||||
auto handle_ping(
|
||||
std::array<uint16_t, 3> cur_version,
|
||||
std::array<uint16_t, 3> required,
|
||||
std::string_view name,
|
||||
std::atomic<std::time_t>& update,
|
||||
std::chrono::seconds lifetime,
|
||||
Success success)
|
||||
{
|
||||
typename RPC::response res{};
|
||||
if (cur_version < required) {
|
||||
|
@ -3289,7 +3295,7 @@ namespace cryptonote { namespace rpc {
|
|||
} else {
|
||||
auto now = std::time(nullptr);
|
||||
auto old = update.exchange(now);
|
||||
bool significant = old + lifetime < now; // Print loudly for the first ping after startup/expiry
|
||||
bool significant = std::chrono::seconds{now - old} > lifetime; // Print loudly for the first ping after startup/expiry
|
||||
if (significant)
|
||||
MGINFO_GREEN("Received ping from " << name << " " << version_printer{cur_version});
|
||||
else
|
||||
|
@ -3307,7 +3313,7 @@ namespace cryptonote { namespace rpc {
|
|||
m_core.ss_version = {req.version_major, req.version_minor, req.version_patch};
|
||||
return handle_ping<STORAGE_SERVER_PING>(
|
||||
{req.version_major, req.version_minor, req.version_patch}, service_nodes::MIN_STORAGE_SERVER_VERSION,
|
||||
"Storage Server", m_core.m_last_storage_server_ping, STORAGE_SERVER_PING_LIFETIME,
|
||||
"Storage Server", m_core.m_last_storage_server_ping, m_core.get_net_config().UPTIME_PROOF_FREQUENCY,
|
||||
[this, &req](bool significant) {
|
||||
m_core.m_storage_lmq_port = req.storage_lmq_port;
|
||||
if (significant)
|
||||
|
@ -3320,7 +3326,7 @@ namespace cryptonote { namespace rpc {
|
|||
m_core.lokinet_version = req.version;
|
||||
return handle_ping<LOKINET_PING>(
|
||||
req.version, service_nodes::MIN_LOKINET_VERSION,
|
||||
"Lokinet", m_core.m_last_lokinet_ping, LOKINET_PING_LIFETIME,
|
||||
"Lokinet", m_core.m_last_lokinet_ping, m_core.get_net_config().UPTIME_PROOF_FREQUENCY,
|
||||
[this](bool significant) { if (significant) m_core.reset_proof_interval(); });
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue