Ability to limit CPU rate for POW (#1734)
* Rate limited POW Formatting Fix wallet build Formatting Fix test Change interval to nanoseconds Formatting * Formatting * Formatting again * Add CLI option to --debug_profile_generate to specify sleep interval. * Move thread sleep to outer while loop
This commit is contained in:
parent
5d175d1757
commit
878cce97e3
11 changed files with 105 additions and 32 deletions
|
@ -32,7 +32,7 @@ TEST (node, block_store_path_failure)
|
|||
auto path (nano::unique_path ());
|
||||
nano::logging logging;
|
||||
logging.init (path);
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max (), nullptr);
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max ());
|
||||
auto node (std::make_shared<nano::node> (init, *service, 24000, path, alarm, logging, work));
|
||||
ASSERT_TRUE (node->wallets.items.empty ());
|
||||
node->stop ();
|
||||
|
@ -47,7 +47,7 @@ TEST (node, password_fanout)
|
|||
nano::node_config config;
|
||||
config.peering_port = 24000;
|
||||
config.logging.init (path);
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max (), nullptr);
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max ());
|
||||
config.password_fanout = 10;
|
||||
auto node (std::make_shared<nano::node> (init, *service, path, alarm, config, work));
|
||||
auto wallet (node->wallets.create (100));
|
||||
|
@ -698,10 +698,12 @@ TEST (node_config, v16_v17_upgrade)
|
|||
// These config options should not be present
|
||||
ASSERT_FALSE (tree.get_optional_child ("tcp_client_timeout"));
|
||||
ASSERT_FALSE (tree.get_optional_child ("tcp_server_timeout"));
|
||||
ASSERT_FALSE (tree.get_optional_child ("pow_sleep_interval"));
|
||||
config.deserialize_json (upgraded, tree);
|
||||
// The config options should be added after the upgrade
|
||||
ASSERT_TRUE (!!tree.get_optional_child ("tcp_client_timeout"));
|
||||
ASSERT_TRUE (!!tree.get_optional_child ("tcp_server_timeout"));
|
||||
ASSERT_TRUE (!!tree.get_optional_child ("pow_sleep_interval"));
|
||||
|
||||
ASSERT_TRUE (upgraded);
|
||||
auto version (tree.get<std::string> ("version"));
|
||||
|
@ -723,19 +725,23 @@ TEST (node_config, v17_values)
|
|||
// Check config is correct
|
||||
tree.put ("tcp_client_timeout", 1);
|
||||
tree.put ("tcp_server_timeout", 0);
|
||||
tree.put ("pow_sleep_interval", 0);
|
||||
config.deserialize_json (upgraded, tree);
|
||||
ASSERT_FALSE (upgraded);
|
||||
ASSERT_EQ (config.tcp_client_timeout.count (), 1);
|
||||
ASSERT_EQ (config.tcp_server_timeout.count (), 0);
|
||||
ASSERT_EQ (config.pow_sleep_interval.count (), 0);
|
||||
|
||||
// Check config is correct with other values
|
||||
tree.put ("tcp_client_timeout", std::numeric_limits<unsigned long>::max () - 100);
|
||||
tree.put ("tcp_server_timeout", std::numeric_limits<unsigned>::max ());
|
||||
tree.put ("pow_sleep_interval", std::numeric_limits<unsigned long>::max () - 100);
|
||||
upgraded = false;
|
||||
config.deserialize_json (upgraded, tree);
|
||||
ASSERT_FALSE (upgraded);
|
||||
ASSERT_EQ (config.tcp_client_timeout.count (), std::numeric_limits<unsigned long>::max () - 100);
|
||||
ASSERT_EQ (config.tcp_server_timeout.count (), std::numeric_limits<unsigned>::max ());
|
||||
ASSERT_EQ (config.pow_sleep_interval.count (), std::numeric_limits<unsigned long>::max () - 100);
|
||||
}
|
||||
|
||||
// Regression test to ensure that deserializing includes changes node via get_required_child
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#include <gtest/gtest.h>
|
||||
|
||||
#include <nano/lib/jsonconfig.hpp>
|
||||
#include <nano/lib/timer.hpp>
|
||||
#include <nano/node/node.hpp>
|
||||
#include <nano/node/wallet.hpp>
|
||||
|
||||
TEST (work, one)
|
||||
{
|
||||
nano::network_params params;
|
||||
nano::work_pool pool (std::numeric_limits<unsigned>::max (), nullptr);
|
||||
nano::work_pool pool (std::numeric_limits<unsigned>::max ());
|
||||
nano::change_block block (1, 1, nano::keypair ().prv, 3, 4);
|
||||
block.block_work_set (pool.generate (block.root ()));
|
||||
uint64_t difficulty;
|
||||
|
@ -18,7 +19,7 @@ TEST (work, one)
|
|||
TEST (work, validate)
|
||||
{
|
||||
nano::network_params params;
|
||||
nano::work_pool pool (std::numeric_limits<unsigned>::max (), nullptr);
|
||||
nano::work_pool pool (std::numeric_limits<unsigned>::max ());
|
||||
nano::send_block send_block (1, 1, 2, nano::keypair ().prv, 4, 6);
|
||||
uint64_t difficulty;
|
||||
ASSERT_TRUE (nano::work_validate (send_block, &difficulty));
|
||||
|
@ -30,7 +31,7 @@ TEST (work, validate)
|
|||
|
||||
TEST (work, cancel)
|
||||
{
|
||||
nano::work_pool pool (std::numeric_limits<unsigned>::max (), nullptr);
|
||||
nano::work_pool pool (std::numeric_limits<unsigned>::max ());
|
||||
auto iterations (0);
|
||||
auto done (false);
|
||||
while (!done)
|
||||
|
@ -47,7 +48,7 @@ TEST (work, cancel)
|
|||
|
||||
TEST (work, cancel_many)
|
||||
{
|
||||
nano::work_pool pool (std::numeric_limits<unsigned>::max (), nullptr);
|
||||
nano::work_pool pool (std::numeric_limits<unsigned>::max ());
|
||||
nano::uint256_union key1 (1);
|
||||
nano::uint256_union key2 (2);
|
||||
nano::uint256_union key3 (1);
|
||||
|
@ -75,10 +76,10 @@ TEST (work, opencl)
|
|||
auto opencl (nano::opencl_work::create (true, { 0, 0, 16 * 1024 }, logging));
|
||||
if (opencl != nullptr)
|
||||
{
|
||||
nano::work_pool pool (std::numeric_limits<unsigned>::max (), opencl ? [&opencl](nano::uint256_union const & root_a, uint64_t difficulty_a) {
|
||||
nano::work_pool pool (std::numeric_limits<unsigned>::max (), std::chrono::nanoseconds (0), opencl ? [&opencl](nano::uint256_union const & root_a, uint64_t difficulty_a) {
|
||||
return opencl->generate_work (root_a, difficulty_a);
|
||||
}
|
||||
: std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> (nullptr));
|
||||
: std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> (nullptr));
|
||||
ASSERT_NE (nullptr, pool.opencl);
|
||||
nano::uint256_union root;
|
||||
uint64_t difficulty (0xff00000000000000);
|
||||
|
@ -121,7 +122,7 @@ TEST (work, opencl_config)
|
|||
|
||||
TEST (work, difficulty)
|
||||
{
|
||||
nano::work_pool pool (std::numeric_limits<unsigned>::max (), nullptr);
|
||||
nano::work_pool pool (std::numeric_limits<unsigned>::max ());
|
||||
nano::uint256_union root (1);
|
||||
uint64_t difficulty1 (0xff00000000000000);
|
||||
uint64_t difficulty2 (0xfff0000000000000);
|
||||
|
@ -143,3 +144,45 @@ TEST (work, difficulty)
|
|||
} while (nonce2 > difficulty3);
|
||||
ASSERT_GT (nonce2, difficulty2);
|
||||
}
|
||||
|
||||
TEST (work, eco_pow)
|
||||
{
|
||||
auto work_func = [](std::promise<std::chrono::nanoseconds> & promise, std::chrono::nanoseconds interval) {
|
||||
nano::work_pool pool (1, interval);
|
||||
constexpr auto num_iterations = 5;
|
||||
|
||||
nano::timer<std::chrono::nanoseconds> timer;
|
||||
timer.start ();
|
||||
for (int i = 0; i < num_iterations; ++i)
|
||||
{
|
||||
nano::uint256_union root (1);
|
||||
uint64_t difficulty1 (0xff00000000000000);
|
||||
uint64_t difficulty2 (0xfff0000000000000);
|
||||
uint64_t work (0);
|
||||
uint64_t nonce (0);
|
||||
do
|
||||
{
|
||||
work = pool.generate (root, difficulty1);
|
||||
nano::work_validate (root, work, &nonce);
|
||||
} while (nonce > difficulty2);
|
||||
ASSERT_GT (nonce, difficulty1);
|
||||
}
|
||||
|
||||
promise.set_value_at_thread_exit (timer.stop ());
|
||||
};
|
||||
|
||||
std::promise<std::chrono::nanoseconds> promise1;
|
||||
std::future<std::chrono::nanoseconds> future1 = promise1.get_future ();
|
||||
std::promise<std::chrono::nanoseconds> promise2;
|
||||
std::future<std::chrono::nanoseconds> future2 = promise2.get_future ();
|
||||
|
||||
std::thread thread1 (work_func, std::ref (promise1), std::chrono::nanoseconds (0));
|
||||
std::thread thread2 (work_func, std::ref (promise2), std::chrono::nanoseconds (100000));
|
||||
|
||||
// Confirm that the eco pow rate limiter is working.
|
||||
// It's possible under some unlucky circumstances that this fails.
|
||||
ASSERT_LT (future1.get (), future2.get ());
|
||||
|
||||
thread1.join ();
|
||||
thread2.join ();
|
||||
}
|
||||
|
|
|
@ -32,9 +32,10 @@ uint64_t nano::work_value (nano::block_hash const & root_a, uint64_t work_a)
|
|||
return result;
|
||||
}
|
||||
|
||||
nano::work_pool::work_pool (unsigned max_threads_a, std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> opencl_a) :
|
||||
nano::work_pool::work_pool (unsigned max_threads_a, std::chrono::nanoseconds pow_rate_limiter_a, std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> opencl_a) :
|
||||
ticket (0),
|
||||
done (false),
|
||||
pow_rate_limiter (pow_rate_limiter_a),
|
||||
opencl (opencl_a)
|
||||
{
|
||||
static_assert (ATOMIC_INT_LOCK_FREE == 2, "Atomic int needed");
|
||||
|
@ -71,6 +72,7 @@ void nano::work_pool::loop (uint64_t thread)
|
|||
blake2b_state hash;
|
||||
blake2b_init (&hash, sizeof (output));
|
||||
std::unique_lock<std::mutex> lock (mutex);
|
||||
auto pow_sleep = pow_rate_limiter;
|
||||
while (!done || !pending.empty ())
|
||||
{
|
||||
auto empty (pending.empty ());
|
||||
|
@ -101,6 +103,12 @@ void nano::work_pool::loop (uint64_t thread)
|
|||
blake2b_init (&hash, sizeof (output));
|
||||
iteration -= 1;
|
||||
}
|
||||
|
||||
// Add a rate limiter (if specified) to the pow calculation to save some CPUs which don't want to operate at full throttle
|
||||
if (pow_sleep != std::chrono::nanoseconds (0))
|
||||
{
|
||||
std::this_thread::sleep_for (pow_sleep);
|
||||
}
|
||||
}
|
||||
lock.lock ();
|
||||
if (ticket == ticket_l)
|
||||
|
@ -162,24 +170,24 @@ void nano::work_pool::stop ()
|
|||
producer_condition.notify_all ();
|
||||
}
|
||||
|
||||
void nano::work_pool::generate (nano::uint256_union const & root_a, std::function<void(boost::optional<uint64_t> const &)> callback_a)
|
||||
void nano::work_pool::generate (nano::uint256_union const & hash_a, std::function<void(boost::optional<uint64_t> const &)> callback_a)
|
||||
{
|
||||
generate (root_a, callback_a, network_params.publish_threshold);
|
||||
generate (hash_a, callback_a, network_params.publish_threshold);
|
||||
}
|
||||
|
||||
void nano::work_pool::generate (nano::uint256_union const & root_a, std::function<void(boost::optional<uint64_t> const &)> callback_a, uint64_t difficulty_a)
|
||||
void nano::work_pool::generate (nano::uint256_union const & hash_a, std::function<void(boost::optional<uint64_t> const &)> callback_a, uint64_t difficulty_a)
|
||||
{
|
||||
assert (!root_a.is_zero ());
|
||||
assert (!hash_a.is_zero ());
|
||||
boost::optional<uint64_t> result;
|
||||
if (opencl)
|
||||
{
|
||||
result = opencl (root_a, difficulty_a);
|
||||
result = opencl (hash_a, difficulty_a);
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock (mutex);
|
||||
pending.push_back ({ root_a, callback_a, difficulty_a });
|
||||
pending.push_back ({ hash_a, callback_a, difficulty_a });
|
||||
}
|
||||
producer_condition.notify_all ();
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
class work_pool final
|
||||
{
|
||||
public:
|
||||
work_pool (unsigned, std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> = nullptr);
|
||||
work_pool (unsigned, std::chrono::nanoseconds = std::chrono::nanoseconds (0), std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> = nullptr);
|
||||
~work_pool ();
|
||||
void loop (uint64_t);
|
||||
void stop ();
|
||||
|
@ -44,6 +44,7 @@ public:
|
|||
std::list<nano::work_item> pending;
|
||||
std::mutex mutex;
|
||||
std::condition_variable producer_condition;
|
||||
std::chrono::nanoseconds pow_rate_limiter;
|
||||
std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> opencl;
|
||||
nano::observer_set<bool> work_observers;
|
||||
};
|
||||
|
|
|
@ -21,10 +21,10 @@ void nano_daemon::daemon::run (boost::filesystem::path const & data_path, nano::
|
|||
config.node.logging.init (data_path);
|
||||
boost::asio::io_context io_ctx;
|
||||
auto opencl (nano::opencl_work::create (config.opencl_enable, config.opencl, config.node.logging));
|
||||
nano::work_pool opencl_work (config.node.work_threads, opencl ? [&opencl](nano::uint256_union const & root_a, uint64_t difficulty_a) {
|
||||
nano::work_pool opencl_work (config.node.work_threads, config.node.pow_sleep_interval, opencl ? [&opencl](nano::uint256_union const & root_a, uint64_t difficulty_a) {
|
||||
return opencl->generate_work (root_a, difficulty_a);
|
||||
}
|
||||
: std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> (nullptr));
|
||||
: std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> (nullptr));
|
||||
nano::alarm alarm (io_ctx);
|
||||
nano::node_init init;
|
||||
try
|
||||
|
|
|
@ -99,7 +99,8 @@ int main (int argc, char * const * argv)
|
|||
("platform", boost::program_options::value<std::string> (), "Defines the <platform> for OpenCL commands")
|
||||
("device", boost::program_options::value<std::string> (), "Defines <device> for OpenCL command")
|
||||
("threads", boost::program_options::value<std::string> (), "Defines <threads> count for OpenCL command")
|
||||
("difficulty", boost::program_options::value<std::string> (), "Defines <difficulty> for OpenCL command, HEX");
|
||||
("difficulty", boost::program_options::value<std::string> (), "Defines <difficulty> for OpenCL command, HEX")
|
||||
("pow_sleep_interval", boost::program_options::value<std::string> (), "Defines the amount to sleep inbetween each pow calculation attempt");
|
||||
// clang-format on
|
||||
|
||||
boost::program_options::variables_map vm;
|
||||
|
@ -164,7 +165,7 @@ int main (int argc, char * const * argv)
|
|||
if (!key.decode_hex (key_it->second.as<std::string> ()))
|
||||
{
|
||||
nano::keypair genesis (key.to_string ());
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max (), nullptr);
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max ());
|
||||
std::cout << "Genesis: " << genesis.prv.data.to_string () << "\n"
|
||||
<< "Public: " << genesis.pub.to_string () << "\n"
|
||||
<< "Account: " << genesis.pub.to_account () << "\n";
|
||||
|
@ -283,7 +284,14 @@ int main (int argc, char * const * argv)
|
|||
}
|
||||
else if (vm.count ("debug_profile_generate"))
|
||||
{
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max (), nullptr);
|
||||
auto pow_rate_limiter = std::chrono::nanoseconds (0);
|
||||
auto pow_sleep_interval_it = vm.find ("pow_sleep_interval");
|
||||
if (pow_sleep_interval_it != vm.cend ())
|
||||
{
|
||||
pow_rate_limiter = std::chrono::nanoseconds (boost::lexical_cast<uint64_t> (pow_sleep_interval_it->second.as<std::string> ()));
|
||||
}
|
||||
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max (), pow_rate_limiter);
|
||||
nano::change_block block (0, 0, nano::keypair ().prv, 0, 0);
|
||||
std::cerr << "Starting generation profiling\n";
|
||||
while (true)
|
||||
|
@ -364,10 +372,10 @@ int main (int argc, char * const * argv)
|
|||
{
|
||||
nano::logging logging;
|
||||
auto opencl (nano::opencl_work::create (true, { platform, device, threads }, logging));
|
||||
nano::work_pool work_pool (std::numeric_limits<unsigned>::max (), opencl ? [&opencl](nano::uint256_union const & root_a, uint64_t difficulty_a) {
|
||||
nano::work_pool work_pool (std::numeric_limits<unsigned>::max (), std::chrono::nanoseconds (0), opencl ? [&opencl](nano::uint256_union const & root_a, uint64_t difficulty_a) {
|
||||
return opencl->generate_work (root_a, difficulty_a);
|
||||
}
|
||||
: std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> (nullptr));
|
||||
: std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> (nullptr));
|
||||
nano::change_block block (0, 0, nano::keypair ().prv, 0, 0);
|
||||
std::cerr << boost::str (boost::format ("Starting OpenCL generation profiling. Platform: %1%. Device: %2%. Threads: %3%. Difficulty: %4$#x\n") % platform % device % threads % difficulty);
|
||||
for (uint64_t i (0); true; ++i)
|
||||
|
@ -402,7 +410,7 @@ int main (int argc, char * const * argv)
|
|||
}
|
||||
else if (vm.count ("debug_profile_verify"))
|
||||
{
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max (), nullptr);
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max ());
|
||||
nano::change_block block (0, 0, nano::keypair ().prv, 0, 0);
|
||||
std::cerr << "Starting verification profiling\n";
|
||||
while (true)
|
||||
|
@ -478,7 +486,7 @@ int main (int argc, char * const * argv)
|
|||
std::cerr << boost::str (boost::format ("Starting pregenerating %1% blocks\n") % max_blocks);
|
||||
nano::system system (24000, 1);
|
||||
nano::node_init init;
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max (), nullptr);
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max ());
|
||||
nano::logging logging;
|
||||
auto path (nano::unique_path ());
|
||||
logging.init (path);
|
||||
|
@ -590,7 +598,7 @@ int main (int argc, char * const * argv)
|
|||
std::cerr << boost::str (boost::format ("Starting pregenerating %1% votes\n") % max_votes);
|
||||
nano::system system (24000, 1);
|
||||
nano::node_init init;
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max (), nullptr);
|
||||
nano::work_pool work (std::numeric_limits<unsigned>::max ());
|
||||
nano::logging logging;
|
||||
auto path (nano::unique_path ());
|
||||
logging.init (path);
|
||||
|
|
|
@ -237,10 +237,10 @@ int run_wallet (QApplication & application, int argc, char * const * argv, boost
|
|||
std::shared_ptr<nano_qt::wallet> gui;
|
||||
nano::set_application_icon (application);
|
||||
auto opencl (nano::opencl_work::create (config.opencl_enable, config.opencl, config.node.logging));
|
||||
nano::work_pool work (config.node.work_threads, opencl ? [&opencl](nano::uint256_union const & root_a, uint64_t difficulty_a) {
|
||||
nano::work_pool work (config.node.work_threads, config.node.pow_sleep_interval, opencl ? [&opencl](nano::uint256_union const & root_a, uint64_t difficulty_a) {
|
||||
return opencl->generate_work (root_a, difficulty_a);
|
||||
}
|
||||
: std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> (nullptr));
|
||||
: std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> (nullptr));
|
||||
nano::alarm alarm (io_ctx);
|
||||
nano::node_init init;
|
||||
nano::node_flags flags;
|
||||
|
|
|
@ -3511,7 +3511,7 @@ nano::inactive_node::inactive_node (boost::filesystem::path const & path_a, uint
|
|||
path (path_a),
|
||||
io_context (std::make_shared<boost::asio::io_context> ()),
|
||||
alarm (*io_context),
|
||||
work (1, nullptr),
|
||||
work (1),
|
||||
peering_port (peering_port_a)
|
||||
{
|
||||
boost::system::error_code error_chmod;
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace
|
|||
{
|
||||
const char * preconfigured_peers_key = "preconfigured_peers";
|
||||
const char * signature_checker_threads_key = "signature_checker_threads";
|
||||
const char * pow_sleep_interval_key = "pow_sleep_interval";
|
||||
const char * default_beta_peer_network = "peering-beta.nano.org";
|
||||
const char * default_live_peer_network = "peering.nano.org";
|
||||
}
|
||||
|
@ -112,6 +113,7 @@ nano::error nano::node_config::serialize_json (nano::jsonconfig & json) const
|
|||
json.put ("unchecked_cutoff_time", unchecked_cutoff_time.count ());
|
||||
json.put ("tcp_client_timeout", tcp_client_timeout.count ());
|
||||
json.put ("tcp_server_timeout", tcp_server_timeout.count ());
|
||||
json.put ("pow_sleep_interval", pow_sleep_interval.count ());
|
||||
nano::jsonconfig websocket_l;
|
||||
websocket_config.serialize_json (websocket_l);
|
||||
json.put_child ("websocket", websocket_l);
|
||||
|
@ -244,6 +246,7 @@ bool nano::node_config::upgrade_json (unsigned version_a, nano::jsonconfig & jso
|
|||
json.put_child ("websocket", websocket_l);
|
||||
json.put ("tcp_client_timeout", tcp_client_timeout.count ());
|
||||
json.put ("tcp_server_timeout", tcp_server_timeout.count ());
|
||||
json.put (pow_sleep_interval_key, pow_sleep_interval.count ());
|
||||
upgraded = true;
|
||||
}
|
||||
case 17:
|
||||
|
@ -379,8 +382,11 @@ nano::error nano::node_config::deserialize_json (bool & upgraded_a, nano::jsonco
|
|||
json.get<bool> ("allow_local_peers", allow_local_peers);
|
||||
json.get<unsigned> (signature_checker_threads_key, signature_checker_threads);
|
||||
|
||||
// Validate ranges
|
||||
auto pow_sleep_interval_l (pow_sleep_interval.count ());
|
||||
json.get (pow_sleep_interval_key, pow_sleep_interval_l);
|
||||
pow_sleep_interval = std::chrono::nanoseconds (pow_sleep_interval_l);
|
||||
|
||||
// Validate ranges
|
||||
if (online_weight_quorum > 100)
|
||||
{
|
||||
json.get_error ().set ("online_weight_quorum must be less than 100");
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
std::chrono::seconds unchecked_cutoff_time{ std::chrono::seconds (4 * 60 * 60) }; // 4 hours
|
||||
std::chrono::seconds tcp_client_timeout{ std::chrono::seconds (5) };
|
||||
std::chrono::seconds tcp_server_timeout{ std::chrono::seconds (30) };
|
||||
std::chrono::nanoseconds pow_sleep_interval{ 0 };
|
||||
static std::chrono::seconds constexpr keepalive_period = std::chrono::seconds (60);
|
||||
static std::chrono::seconds constexpr keepalive_cutoff = keepalive_period * 5;
|
||||
static std::chrono::minutes constexpr wallet_backup_interval = std::chrono::minutes (5);
|
||||
|
|
|
@ -21,7 +21,7 @@ std::string nano::error_system_messages::message (int ev) const
|
|||
|
||||
nano::system::system (uint16_t port_a, uint16_t count_a) :
|
||||
alarm (io_ctx),
|
||||
work (1, nullptr)
|
||||
work (1)
|
||||
{
|
||||
auto scale_str = std::getenv ("DEADLINE_SCALE_FACTOR");
|
||||
if (scale_str)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue