diff --git a/nano/core_test/toml.cpp b/nano/core_test/toml.cpp index 986869ae3..6192abcae 100644 --- a/nano/core_test/toml.cpp +++ b/nano/core_test/toml.cpp @@ -308,7 +308,7 @@ TEST (toml_config, daemon_config_deserialize_defaults) ASSERT_EQ (conf.node.signature_checker_threads, defaults.node.signature_checker_threads); ASSERT_EQ (conf.node.unchecked_cutoff_time, defaults.node.unchecked_cutoff_time); ASSERT_EQ (conf.node.use_memory_pools, defaults.node.use_memory_pools); - ASSERT_EQ (conf.node.vote_generator_delay, defaults.node.vote_generator_delay); + ASSERT_EQ (conf.node.vote_generator.delay, defaults.node.vote_generator.delay); ASSERT_EQ (conf.node.vote_minimum, defaults.node.vote_minimum); ASSERT_EQ (conf.node.work_peers, defaults.node.work_peers); ASSERT_EQ (conf.node.work_threads, defaults.node.work_threads); @@ -473,7 +473,6 @@ TEST (toml_config, daemon_config_deserialize_no_defaults) signature_checker_threads = 999 unchecked_cutoff_time = 999 use_memory_pools = false - vote_generator_delay = 999 vote_minimum = "999" work_peers = ["dev.org:999"] work_threads = 999 @@ -670,6 +669,9 @@ TEST (toml_config, daemon_config_deserialize_no_defaults) duplicate_filter_cutoff = 999 minimum_fanout = 99 + [node.vote_generator] + delay = 999 + [opencl] device = 999 enable = true @@ -740,7 +742,7 @@ TEST (toml_config, daemon_config_deserialize_no_defaults) ASSERT_NE (conf.node.signature_checker_threads, defaults.node.signature_checker_threads); ASSERT_NE (conf.node.unchecked_cutoff_time, defaults.node.unchecked_cutoff_time); ASSERT_NE (conf.node.use_memory_pools, defaults.node.use_memory_pools); - ASSERT_NE (conf.node.vote_generator_delay, defaults.node.vote_generator_delay); + ASSERT_NE (conf.node.vote_generator.delay, defaults.node.vote_generator.delay); ASSERT_NE (conf.node.vote_minimum, defaults.node.vote_minimum); ASSERT_NE (conf.node.work_peers, defaults.node.work_peers); ASSERT_NE (conf.node.work_threads, defaults.node.work_threads); diff --git a/nano/node/node.cpp b/nano/node/node.cpp index 98edb92b4..da96cae94 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -177,9 +177,9 @@ nano::node::node (std::shared_ptr io_ctx_a, std::filesy vote_processor{ *vote_processor_impl }, vote_cache_processor_impl{ std::make_unique (config.vote_processor, vote_router, vote_cache, stats, logger) }, vote_cache_processor{ *vote_cache_processor_impl }, - generator_impl{ std::make_unique (config, *this, ledger, wallets, vote_processor, history, network, stats, logger, /* non-final */ false, loopback_channel) }, + generator_impl{ std::make_unique (config.vote_generator, *this, ledger, wallets, vote_processor, history, network, stats, logger, /* non-final */ false, loopback_channel) }, generator{ *generator_impl }, - final_generator_impl{ std::make_unique (config, *this, ledger, wallets, vote_processor, history, network, stats, logger, /* final */ true, loopback_channel) }, + final_generator_impl{ std::make_unique (config.vote_generator, *this, ledger, wallets, vote_processor, history, network, stats, logger, /* final */ true, loopback_channel) }, final_generator{ *final_generator_impl }, scheduler_impl{ std::make_unique (config, *this, ledger, ledger_notifications, bucketing, active, online_reps, vote_cache, cementing_set, stats, logger) }, scheduler{ *scheduler_impl }, diff --git a/nano/node/nodeconfig.cpp b/nano/node/nodeconfig.cpp index cf8ee6fc8..31d585688 100644 --- a/nano/node/nodeconfig.cpp +++ b/nano/node/nodeconfig.cpp @@ -119,7 +119,6 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const toml.put ("block_processor_batch_max_time", block_processor_batch_max_time.count (), "The maximum time the block processor can continuously process blocks for.\ntype:milliseconds"); toml.put ("allow_local_peers", allow_local_peers, "Enable or disable local host peering.\ntype:bool"); toml.put ("vote_minimum", vote_minimum.to_string_dec (), "Local representatives do not vote if the delegated weight is under this threshold. Saves on system resources.\ntype:string,amount,raw"); - toml.put ("vote_generator_delay", vote_generator_delay.count (), "Delay before votes are sent to allow for efficient bundling of hashes in votes.\ntype:milliseconds"); toml.put ("unchecked_cutoff_time", unchecked_cutoff_time.count (), "Number of seconds before deleting an unchecked entry.\nWarning: lower values (e.g., 3600 seconds, or 1 hour) may result in unsuccessful bootstraps, especially a bootstrap from scratch.\ntype:seconds"); toml.put ("pow_sleep_interval", pow_sleep_interval.count (), "Time to sleep between batch work generation attempts. Reduces max CPU usage at the expense of a longer generation time.\ntype:nanoseconds"); toml.put ("external_address", external_address, "The external address of this node (NAT). If not set, the node will request this information via UPnP.\ntype:string,ip"); @@ -245,6 +244,10 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const block_processor.serialize (block_processor_l); toml.put_child ("block_processor", block_processor_l); + nano::tomlconfig vote_generator_l; + vote_generator.serialize (vote_generator_l); + toml.put_child ("vote_generator", vote_generator_l); + nano::tomlconfig vote_processor_l; vote_processor.serialize (vote_processor_l); toml.put_child ("vote_processor", vote_processor_l); @@ -406,6 +409,12 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml) block_processor.deserialize (config_l); } + if (toml.has_key ("vote_generator")) + { + auto config_l = toml.get_required_child ("vote_generator"); + vote_generator.deserialize (config_l); + } + if (toml.has_key ("vote_processor")) { auto config_l = toml.get_required_child ("vote_processor"); @@ -562,10 +571,6 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml) toml.get_error ().set ("vote_minimum contains an invalid decimal amount"); } - auto delay_l = vote_generator_delay.count (); - toml.get ("vote_generator_delay", delay_l); - vote_generator_delay = std::chrono::milliseconds (delay_l); - auto block_processor_batch_max_time_l = block_processor_batch_max_time.count (); toml.get ("block_processor_batch_max_time", block_processor_batch_max_time_l); block_processor_batch_max_time = std::chrono::milliseconds (block_processor_batch_max_time_l); diff --git a/nano/node/nodeconfig.hpp b/nano/node/nodeconfig.hpp index 152a0e8ed..f5b70ce24 100644 --- a/nano/node/nodeconfig.hpp +++ b/nano/node/nodeconfig.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -85,7 +86,6 @@ public: nano::amount receive_minimum{ nano::nano_ratio / 1000 / 1000 }; // 0.000001 nano nano::amount vote_minimum{ nano::Knano_ratio }; // 1000 nano nano::amount rep_crawler_weight_minimum{ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" }; - std::chrono::milliseconds vote_generator_delay{ std::chrono::milliseconds (100) }; nano::amount online_weight_minimum{ 60000 * nano::Knano_ratio }; // 60 million nano /* * The minimum vote weight that a representative must have for its vote to be counted. @@ -150,6 +150,7 @@ public: nano::rep_crawler_config rep_crawler; nano::block_processor_config block_processor; nano::active_elections_config active_elections; + nano::vote_generator_config vote_generator; nano::vote_processor_config vote_processor; nano::peer_history_config peer_history; nano::transport::tcp_config tcp; diff --git a/nano/node/vote_generator.cpp b/nano/node/vote_generator.cpp index 5c34d8130..70bcecc6f 100644 --- a/nano/node/vote_generator.cpp +++ b/nano/node/vote_generator.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -16,21 +17,21 @@ #include -nano::vote_generator::vote_generator (nano::node_config const & config_a, nano::node & node_a, nano::ledger & ledger_a, nano::wallets & wallets_a, nano::vote_processor & vote_processor_a, nano::local_vote_history & history_a, nano::network & network_a, nano::stats & stats_a, nano::logger & logger_a, bool is_final_a, std::shared_ptr inproc_channel_a) : +nano::vote_generator::vote_generator (vote_generator_config const & config_a, nano::node & node_a, nano::ledger & ledger_a, nano::wallets & wallets_a, nano::vote_processor & vote_processor_a, nano::local_vote_history & history_a, nano::network & network_a, nano::stats & stats_a, nano::logger & logger_a, bool is_final_a, std::shared_ptr inproc_channel_a) : config (config_a), node (node_a), ledger (ledger_a), wallets (wallets_a), vote_processor (vote_processor_a), history (history_a), - spacing_impl{ std::make_unique (config_a.network_params.voting.delay) }, + spacing_impl{ std::make_unique (node_a.network_params.voting.delay) }, spacing{ *spacing_impl }, network (network_a), stats (stats_a), logger (logger_a), is_final (is_final_a), inproc_channel{ inproc_channel_a }, - vote_generation_queue{ stats, nano::stat::type::vote_generator, is_final ? nano::thread_role::name::voting_final : nano::thread_role::name::voting, /* single threaded */ 1, /* max queue size */ 1024 * 32, /* max batch size */ 256 } + vote_generation_queue{ stats, nano::stat::type::vote_generator, is_final ? nano::thread_role::name::voting_final : nano::thread_role::name::voting, /* single threaded */ 1, config.max_queue, config.batch_size } { vote_generation_queue.process_batch = [this] (auto & batch) { process_batch (batch); @@ -246,7 +247,7 @@ void nano::vote_generator::reply (nano::unique_lock & lock_a, reque stats.add (nano::stat::type::requests, nano::stat::detail::requests_generated_hashes, stat::dir::in, hashes.size ()); vote (hashes, roots, [this, channel = request_a.second] (std::shared_ptr const & vote_a) { - nano::confirm_ack confirm{ config.network_params.network, vote_a }; + nano::confirm_ack confirm{ node.network_params.network, vote_a }; channel->send (confirm, nano::transport::traffic_type::vote_reply); stats.inc (nano::stat::type::requests, nano::stat::detail::requests_generated_votes, stat::dir::in); }); @@ -292,8 +293,8 @@ void nano::vote_generator::run () nano::unique_lock lock{ mutex }; while (!stopped) { - // Wait for at most vote_generator_delay in case no further notification is received - condition.wait_for (lock, config.vote_generator_delay, [this] () { + // Wait for at most delay in case no further notification is received + condition.wait_for (lock, config.delay, [this] () { return stopped || broadcast_predicate () || !requests.empty (); }); @@ -315,7 +316,7 @@ void nano::vote_generator::run () if (broadcast_predicate ()) { broadcast (lock); - next_broadcast = std::chrono::steady_clock::now () + config.vote_generator_delay; + next_broadcast = std::chrono::steady_clock::now () + config.delay; } if (!requests.empty ()) @@ -362,4 +363,26 @@ nano::stat::type nano::vote_generator::stat_type () const nano::log::type nano::vote_generator::log_type () const { return is_final ? nano::log::type::vote_generator_final : nano::log::type::vote_generator; +} + +/* + * vote_generator_config + */ + +nano::error nano::vote_generator_config::serialize (nano::tomlconfig & toml) const +{ + toml.put ("max_queue", max_queue, "Maximum number of entries in the vote generation queue. \ntype:uint64"); + toml.put ("batch_size", batch_size, "Maximum number of entries to process in a single batch. \ntype:uint64"); + toml.put ("delay", delay.count (), "Delay before votes are sent to allow for efficient bundling of hashes in votes. \ntype:milliseconds"); + + return toml.get_error (); +} + +nano::error nano::vote_generator_config::deserialize (nano::tomlconfig & toml) +{ + toml.get ("max_queue", max_queue); + toml.get ("batch_size", batch_size); + toml.get_duration ("delay", delay); + + return toml.get_error (); } \ No newline at end of file diff --git a/nano/node/vote_generator.hpp b/nano/node/vote_generator.hpp index 0233bf907..f8edc4d3e 100644 --- a/nano/node/vote_generator.hpp +++ b/nano/node/vote_generator.hpp @@ -25,6 +25,18 @@ namespace mi = boost::multi_index; namespace nano { +class vote_generator_config final +{ +public: + nano::error serialize (nano::tomlconfig & toml) const; + nano::error deserialize (nano::tomlconfig & toml); + +public: + size_t max_queue{ 1024 * 32 }; + size_t batch_size{ 256 }; + std::chrono::milliseconds delay{ 100ms }; +}; + class vote_generator final { private: @@ -34,7 +46,7 @@ private: std::chrono::steady_clock::time_point next_broadcast = { std::chrono::steady_clock::now () }; public: - vote_generator (nano::node_config const &, nano::node &, nano::ledger &, nano::wallets &, nano::vote_processor &, nano::local_vote_history &, nano::network &, nano::stats &, nano::logger &, bool is_final, std::shared_ptr inproc_channel); + vote_generator (vote_generator_config const &, nano::node &, nano::ledger &, nano::wallets &, nano::vote_processor &, nano::local_vote_history &, nano::network &, nano::stats &, nano::logger &, bool is_final, std::shared_ptr inproc_channel); ~vote_generator (); /** Queue items for vote generation, or broadcast votes already in cache */ @@ -63,7 +75,7 @@ private: nano::log::type log_type () const; private: // Dependencies - nano::node_config const & config; + vote_generator_config const & config; nano::node & node; nano::ledger & ledger; nano::wallets & wallets;