diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index 6594834d..dd902056 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -39,9 +39,8 @@ TEST (active_transactions, adjusted_difficulty_priority) nano::system system; nano::node_config node_config (24000, system.logging); node_config.enable_voting = false; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto & node1 = *system.add_node (node_config, node_flags); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto & node1 = *system.add_node (node_config); nano::genesis genesis; nano::keypair key1, key2, key3; @@ -123,10 +122,9 @@ TEST (active_transactions, keep_local) nano::node_config node_config (24000, system.logging); node_config.enable_voting = false; node_config.active_elections_size = 3; //bound to 3, wont drop wallet created transactions, but good to test dropping remote - //delay_frontier_confirmation_height_updating to allow the test to before - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto & node1 = *system.add_node (node_config, node_flags); + // Disable frontier confirmation to allow the test to finish before + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto & node1 = *system.add_node (node_config); auto & wallet (*system.wallet (0)); nano::genesis genesis; //key 1/2 will be managed by the wallet @@ -179,10 +177,9 @@ TEST (active_transactions, prioritize_chains) nano::node_config node_config (24000, system.logging); node_config.enable_voting = false; node_config.active_elections_size = 4; //bound to 3, wont drop wallet created transactions, but good to test dropping remote - //delay_frontier_confirmation_height_updating to allow the test to before - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto & node1 = *system.add_node (node_config, node_flags); + // Disable frontier confirmation to allow the test to finish before + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto & node1 = *system.add_node (node_config); nano::genesis genesis; nano::keypair key1, key2, key3; diff --git a/nano/core_test/conflicts.cpp b/nano/core_test/conflicts.cpp index 89eb388c..4f7da5f9 100644 --- a/nano/core_test/conflicts.cpp +++ b/nano/core_test/conflicts.cpp @@ -193,9 +193,9 @@ TEST (conflicts, reprioritize) TEST (conflicts, dependency) { nano::system system; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node1 = system.add_node (nano::node_config (24000, system.logging), node_flags); + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node1 = system.add_node (node_config); nano::genesis genesis; nano::keypair key1; auto send1 (std::make_shared (genesis.hash (), key1.pub, nano::genesis_amount - nano::xrb_ratio, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0)); diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index 4b1e24ea..1874e83f 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -815,9 +815,8 @@ TEST (votes, add_existing) nano::system system; nano::node_config node_config (24000, system.logging); node_config.online_weight_minimum = std::numeric_limits::max (); - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto & node1 = *system.add_node (node_config, node_flags); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto & node1 = *system.add_node (node_config); nano::genesis genesis; nano::keypair key1; auto send1 (std::make_shared (genesis.hash (), key1.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0)); diff --git a/nano/core_test/network.cpp b/nano/core_test/network.cpp index 3a1a4440..191bb360 100644 --- a/nano/core_test/network.cpp +++ b/nano/core_test/network.cpp @@ -1559,10 +1559,11 @@ TEST (confirmation_height, single) TEST (confirmation_height, multiple_accounts) { nano::system system; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - system.add_node (nano::node_config (24001, system.logging), node_flags); - system.add_node (nano::node_config (24002, system.logging), node_flags); + nano::node_config node_config (24001, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + system.add_node (node_config); + node_config.peering_port = 24002; + system.add_node (node_config); nano::keypair key1; nano::keypair key2; nano::keypair key3; @@ -1757,10 +1758,11 @@ TEST (confirmation_height, gap_bootstrap) TEST (confirmation_height, gap_live) { nano::system system; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - system.add_node (nano::node_config (24001, system.logging), node_flags); - system.add_node (nano::node_config (24002, system.logging), node_flags); + nano::node_config node_config (24001, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + system.add_node (node_config); + node_config.peering_port = 24002; + system.add_node (node_config); nano::keypair destination; system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); system.wallet (1)->insert_adhoc (destination.prv); @@ -1837,9 +1839,9 @@ TEST (confirmation_height, gap_live) TEST (confirmation_height, send_receive_between_2_accounts) { nano::system system; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node = system.add_node (nano::node_config (24000, system.logging), node_flags); + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node = system.add_node (node_config); nano::keypair key1; system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); nano::block_hash latest (node->latest (nano::test_genesis_key.pub)); @@ -1917,9 +1919,9 @@ TEST (confirmation_height, send_receive_between_2_accounts) TEST (confirmation_height, send_receive_self) { nano::system system; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node = system.add_node (nano::node_config (24000, system.logging), node_flags); + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node = system.add_node (node_config); system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); nano::block_hash latest (node->latest (nano::test_genesis_key.pub)); @@ -1976,9 +1978,9 @@ TEST (confirmation_height, send_receive_self) TEST (confirmation_height, all_block_types) { nano::system system; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node = system.add_node (nano::node_config (24000, system.logging), node_flags); + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node = system.add_node (node_config); system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); nano::block_hash latest (node->latest (nano::test_genesis_key.pub)); nano::keypair key1; @@ -2178,9 +2180,9 @@ TEST (confirmation_height, observers) TEST (confirmation_height, modified_chain) { nano::system system; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node = system.add_node (nano::node_config (24000, system.logging), node_flags); + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node = system.add_node (node_config); system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); nano::block_hash latest (node->latest (nano::test_genesis_key.pub)); @@ -2216,9 +2218,9 @@ namespace nano TEST (confirmation_height, pending_observer_callbacks) { nano::system system; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node = system.add_node (nano::node_config (24000, system.logging), node_flags); + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node = system.add_node (node_config); system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); nano::block_hash latest (node->latest (nano::test_genesis_key.pub)); diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index 678ae79c..5231c0bc 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -1709,9 +1709,8 @@ TEST (node, rep_self_vote) nano::system system; nano::node_config node_config (24000, system.logging); node_config.online_weight_minimum = std::numeric_limits::max (); - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node0 = system.add_node (node_config, node_flags); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node0 = system.add_node (node_config); nano::keypair rep_big; { auto transaction0 (node0->store.tx_begin_write ()); @@ -1814,10 +1813,11 @@ TEST (node, bootstrap_bulk_push) TEST (node, bootstrap_fork_open) { nano::system system0; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node0 = system0.add_node (nano::node_config (24000, system0.logging), node_flags); - auto node1 = system0.add_node (nano::node_config (24001, system0.logging), node_flags); + nano::node_config node_config (24000, system0.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node0 = system0.add_node (node_config); + node_config.peering_port = 24001; + auto node1 = system0.add_node (node_config); system0.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); nano::keypair key0; nano::send_block send0 (system0.nodes[0]->latest (nano::test_genesis_key.pub), key0.pub, nano::genesis_amount - 500, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0); @@ -1853,7 +1853,7 @@ TEST (node, bootstrap_confirm_frontiers) nano::system system0 (24000, 1); nano::system system1 (24001, 1); auto node0 (system0.nodes[0]); - auto node1 (system1.nodes[0]); + auto node1 (system0.nodes[0]); system0.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); nano::keypair key0; // node0 knows about send0 but node1 doesn't. @@ -2585,10 +2585,11 @@ TEST (node, vote_by_hash_epoch_block_republish) TEST (node, epoch_conflict_confirm) { nano::system system; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node0 = system.add_node (nano::node_config (24000, system.logging), node_flags); - auto node1 = system.add_node (nano::node_config (24001, system.logging), node_flags); + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node0 = system.add_node (node_config); + node_config.peering_port = 24001; + auto node1 = system.add_node (node_config); nano::keypair key; nano::genesis genesis; nano::keypair epoch_signer (nano::test_genesis_key); @@ -2786,9 +2787,9 @@ TEST (node, block_processor_reject_state) TEST (node, block_processor_reject_rolled_back) { nano::system system; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto & node = *system.add_node (nano::node_config (24000, system.logging), node_flags); + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto & node = *system.add_node (node_config); nano::genesis genesis; auto send1 (std::make_shared (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::test_genesis_key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0)); node.work_generate_blocking (*send1); @@ -3084,10 +3085,11 @@ TEST (node, bidirectional_tcp) { nano::system system; nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; node_flags.disable_udp = true; // Disable UDP connections - auto node1 = system.add_node (nano::node_config (24000, system.logging), node_flags); - nano::node_config node_config (24001, system.logging); + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node1 = system.add_node (node_config, node_flags); + node_config.peering_port = 24001; node_config.tcp_incoming_connections_max = 0; // Disable incoming TCP connections for node 2 auto node2 = system.add_node (node_config, node_flags); // Check network connections @@ -3155,9 +3157,9 @@ TEST (confirmation_height, prioritize_frontiers) { nano::system system; // Prevent frontiers being confirmed as it will affect the priorization checking - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node = system.add_node (nano::node_config (24001, system.logging), node_flags); + nano::node_config node_config (24001, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node = system.add_node (node_config); nano::keypair key1; nano::keypair key2; @@ -3274,13 +3276,9 @@ TEST (confirmation_height, prioritize_frontiers) transaction.refresh (); node->active.prioritize_frontiers_for_confirmation (transaction, std::chrono::seconds (1), std::chrono::seconds (1)); ASSERT_TRUE (priority_orders_match (node->active.priority_wallet_cementable_frontiers, std::array{ key3.pub, nano::genesis_account, key4.pub, key1.pub, key2.pub })); + node->active.confirm_frontiers (transaction); // Check that the active transactions roots contains the frontiers - { - std::lock_guard guard (node->active.mutex); - node->active.next_frontier_check = std::chrono::steady_clock::now (); - } - system.deadline_set (std::chrono::seconds (10)); while (node->active.size () != num_accounts) { @@ -3295,6 +3293,61 @@ TEST (confirmation_height, prioritize_frontiers) } } +TEST (confirmation_height, frontiers_confirmation_mode) +{ + nano::genesis genesis; + nano::keypair key; + // Always mode + { + nano::system system; + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::always; + auto node = system.add_node (node_config); + nano::state_block send (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, node->work_generate_blocking (genesis.hash ())); + { + auto transaction = node->store.tx_begin_write (); + ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, send).code); + } + system.deadline_set (5s); + while (node->active.size () != 1) + { + ASSERT_NO_ERROR (system.poll ()); + } + } + // Auto mode + { + nano::system system; + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::automatic; + auto node = system.add_node (node_config); + nano::state_block send (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, node->work_generate_blocking (genesis.hash ())); + { + auto transaction = node->store.tx_begin_write (); + ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, send).code); + } + system.deadline_set (5s); + while (node->active.size () != 1) + { + ASSERT_NO_ERROR (system.poll ()); + } + } + // Disabled mode + { + nano::system system; + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node = system.add_node (node_config); + nano::state_block send (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, node->work_generate_blocking (genesis.hash ())); + { + auto transaction = node->store.tx_begin_write (); + ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, send).code); + } + system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); + std::this_thread::sleep_for (std::chrono::seconds (1)); + ASSERT_EQ (0, node->active.size ()); + } +} + TEST (active_difficulty, recalculate_work) { nano::system system; diff --git a/nano/core_test/toml.cpp b/nano/core_test/toml.cpp index 69ca02fc..f5cfc44c 100644 --- a/nano/core_test/toml.cpp +++ b/nano/core_test/toml.cpp @@ -257,6 +257,7 @@ TEST (toml, daemon_config_deserialize_no_defaults) work_threads = 999 work_watcher_period = 999 max_work_generate_multiplier = 1.0 + frontiers_confirmation = "always" [node.diagnostics.txn_tracking] enable = true ignore_writes_below_block_processor_max_time = false @@ -369,6 +370,7 @@ TEST (toml, daemon_config_deserialize_no_defaults) ASSERT_NE (conf.node.io_threads, defaults.node.io_threads); ASSERT_NE (conf.node.lmdb_max_dbs, defaults.node.lmdb_max_dbs); ASSERT_NE (conf.node.max_work_generate_multiplier, defaults.node.max_work_generate_multiplier); + ASSERT_NE (conf.node.frontiers_confirmation, defaults.node.frontiers_confirmation); ASSERT_NE (conf.node.network_threads, defaults.node.network_threads); ASSERT_NE (conf.node.work_watcher_period, defaults.node.work_watcher_period); ASSERT_NE (conf.node.online_weight_minimum, defaults.node.online_weight_minimum); @@ -551,4 +553,18 @@ TEST (toml, daemon_config_deserialize_errors) conf.deserialize_toml (toml); ASSERT_EQ (toml.get_error ().get_message (), "max_work_generate_multiplier must be greater than or equal to 1"); + + std::stringstream ss_frontiers_confirmation; + ss_frontiers_confirmation << R"toml( + [node] + frontiers_confirmation = "randomstring" + )toml"; + + nano::tomlconfig toml2; + toml2.read (ss_frontiers_confirmation); + nano::daemon_config conf2; + conf2.deserialize_toml (toml2); + + ASSERT_EQ (toml2.get_error ().get_message (), "frontiers_confirmation value is invalid (available: always, auto, disabled)"); + ASSERT_EQ (conf2.node.frontiers_confirmation, nano::frontiers_confirmation_mode::invalid); } diff --git a/nano/node/active_transactions.cpp b/nano/node/active_transactions.cpp index c2081b3b..f5d07632 100644 --- a/nano/node/active_transactions.cpp +++ b/nano/node/active_transactions.cpp @@ -13,7 +13,7 @@ nano::active_transactions::active_transactions (nano::node & node_a) : node (node_a), multipliers_cb (20, 1.), trended_active_difficulty (node.network_params.network.publish_threshold), -next_frontier_check (steady_clock::now () + (node_a.flags.delay_frontier_confirmation_height_updating ? 60s : 0s)), +next_frontier_check (steady_clock::now ()), thread ([this]() { nano::thread_role::set (nano::thread_role::name::request_loop); request_loop (); @@ -35,8 +35,10 @@ void nano::active_transactions::confirm_frontiers (nano::transaction const & tra { // Limit maximum count of elections to start bool representative (node.config.enable_voting && node.wallets.reps_count > 0); - /* Check less frequently for non-representative nodes */ - auto representative_factor = representative ? 3min : 15min; + bool half_princpal_representative (representative && node.wallets.half_principal_reps_count > 0); + /* Check less frequently for regular nodes in auto mode */ + bool agressive_mode (half_princpal_representative || node.config.frontiers_confirmation == nano::frontiers_confirmation_mode::always); + auto agressive_factor = agressive_mode ? 3min : 15min; // Decrease check time for test network auto is_test_network = node.network_params.network.is_test_network (); int test_network_factor = is_test_network ? 1000 : 1; @@ -46,10 +48,11 @@ void nano::active_transactions::confirm_frontiers (nano::transaction const & tra auto check_time_exceeded = std::chrono::steady_clock::now () >= next_frontier_check; lk.unlock (); auto low_active_elections = roots_size < max_elections; + bool wallets_check_required = (!skip_wallets || !priority_wallet_cementable_frontiers.empty ()) && !agressive_mode; // To minimise dropping real-time transactions, set the maximum number of elections // for cementing frontiers to half the total active election maximum. const auto max_active = node.config.active_elections_size / 2; - if (roots_size <= max_active && (check_time_exceeded || (!is_test_network && low_active_elections))) + if (roots_size <= max_active && (check_time_exceeded || wallets_check_required || (!is_test_network && low_active_elections && agressive_mode))) { // When the number of active elections is low increase max number of elections for setting confirmation height. if (max_active > roots_size + max_elections) @@ -100,7 +103,7 @@ void nano::active_transactions::confirm_frontiers (nano::transaction const & tra // 4 times slower check if all frontiers were confirmed auto fully_confirmed_factor = frontiers_fully_confirmed ? 4 : 1; // Calculate next check time - next_frontier_check = steady_clock::now () + (representative_factor * fully_confirmed_factor / test_network_factor); + next_frontier_check = steady_clock::now () + (agressive_factor * fully_confirmed_factor / test_network_factor); } } @@ -115,9 +118,10 @@ void nano::active_transactions::request_confirm (std::unique_lock & std::deque> rebroadcast_bundle; std::deque, std::shared_ptr>>>> confirm_req_bundle; - // Confirm frontiers when there aren't many confirmations already pending and node finished initial bootstrap + /* Confirm frontiers when there aren't many confirmations already pending and node finished initial bootstrap + In auto mode start confirm only if node contains almost principal representative (half of required for principal weight) */ lock_a.unlock (); - if (node.pending_confirmation_height.size () < confirmed_frontiers_max_pending_cut_off && node.store.block_count (transaction).sum () >= node.ledger.bootstrap_weight_max_blocks) + if (node.config.frontiers_confirmation != nano::frontiers_confirmation_mode::disabled && node.pending_confirmation_height.size () < confirmed_frontiers_max_pending_cut_off && node.store.block_count (transaction).sum () >= node.ledger.bootstrap_weight_max_blocks) { confirm_frontiers (transaction); } @@ -401,6 +405,10 @@ void nano::active_transactions::prioritize_frontiers_for_confirmation (nano::tra std::lock_guard lock (node.wallets.mutex); auto wallet_transaction (node.wallets.tx_begin_read ()); auto const & items = node.wallets.items; + if (items.empty ()) + { + skip_wallets = true; + } for (auto item_it = items.cbegin (); item_it != items.cend (); ++item_it) { // Skip this wallet if it has been traversed already while there are others still awaiting diff --git a/nano/node/nodeconfig.cpp b/nano/node/nodeconfig.cpp index dcbc1a1b..fc0dd3f3 100644 --- a/nano/node/nodeconfig.cpp +++ b/nano/node/nodeconfig.cpp @@ -98,6 +98,7 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const toml.put ("backup_before_upgrade", backup_before_upgrade, "Backup the ledger database before performing upgrades\ntype:bool"); toml.put ("work_watcher_period", work_watcher_period.count (), "Time between checks for confirmation and re-generating higher difficulty work if unconfirmed, for blocks in the work watcher.\ntype:seconds"); toml.put ("max_work_generate_multiplier", max_work_generate_multiplier, "Maximum allowed difficulty multiplier for work generation\ntype:double,[1..]"); + toml.put ("frontiers_confirmation", serialize_frontiers_confirmation (frontiers_confirmation), "Mode for force frontiers confirmation\ntype:string"); auto work_peers_l (toml.create_array ("work_peers", "A list of \"address:port\" entries to identify work peers")); for (auto i (work_peers.begin ()), n (work_peers.end ()); i != n; ++i) @@ -319,6 +320,12 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml) toml.get ("max_work_generate_multiplier", max_work_generate_multiplier); max_work_generate_difficulty = nano::difficulty::from_multiplier (max_work_generate_multiplier, network.publish_threshold); + if (toml.has_key ("frontiers_confirmation")) + { + auto frontiers_confirmation_l (toml.get ("frontiers_confirmation")); + frontiers_confirmation = deserialize_frontiers_confirmation (frontiers_confirmation_l); + } + // Validate ranges if (online_weight_quorum > 100) { @@ -352,6 +359,10 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml) { toml.get_error ().set ("max_work_generate_multiplier must be greater than or equal to 1"); } + if (frontiers_confirmation == nano::frontiers_confirmation_mode::invalid) + { + toml.get_error ().set ("frontiers_confirmation value is invalid (available: always, auto, disabled)"); + } } catch (std::runtime_error const & ex) { @@ -761,6 +772,41 @@ nano::error nano::node_config::deserialize_json (bool & upgraded_a, nano::jsonco return json.get_error (); } +std::string nano::node_config::serialize_frontiers_confirmation (nano::frontiers_confirmation_mode mode_a) const +{ + switch (mode_a) + { + case nano::frontiers_confirmation_mode::always: + return "always"; + case nano::frontiers_confirmation_mode::automatic: + return "auto"; + case nano::frontiers_confirmation_mode::disabled: + return "disabled"; + default: + return "auto"; + } +} + +nano::frontiers_confirmation_mode nano::node_config::deserialize_frontiers_confirmation (std::string const & string_a) +{ + if (string_a == "always") + { + return nano::frontiers_confirmation_mode::always; + } + else if (string_a == "auto") + { + return nano::frontiers_confirmation_mode::automatic; + } + else if (string_a == "disabled") + { + return nano::frontiers_confirmation_mode::disabled; + } + else + { + return nano::frontiers_confirmation_mode::invalid; + } +} + nano::account nano::node_config::random_representative () { assert (!preconfigured_representatives.empty ()); diff --git a/nano/node/nodeconfig.hpp b/nano/node/nodeconfig.hpp index 56d3f668..9c964015 100644 --- a/nano/node/nodeconfig.hpp +++ b/nano/node/nodeconfig.hpp @@ -17,6 +17,15 @@ namespace nano { class tomlconfig; + +enum class frontiers_confirmation_mode : uint8_t +{ + always, // Always confirm frontiers + automatic, // Always mode if node contains representative with at least 50% of principal weight, less frequest requests if not + disabled, // Do not confirm frontiers + invalid +}; + /** * Node configuration */ @@ -84,6 +93,9 @@ public: std::chrono::seconds work_watcher_period{ std::chrono::seconds (5) }; double max_work_generate_multiplier{ 64. }; uint64_t max_work_generate_difficulty{ nano::network_constants::publish_full_threshold }; + nano::frontiers_confirmation_mode frontiers_confirmation{ nano::frontiers_confirmation_mode::automatic }; + std::string serialize_frontiers_confirmation (nano::frontiers_confirmation_mode) const; + nano::frontiers_confirmation_mode deserialize_frontiers_confirmation (std::string const &); static unsigned json_version () { return 18; @@ -104,7 +116,6 @@ public: bool disable_unchecked_cleanup{ false }; bool disable_unchecked_drop{ true }; bool fast_bootstrap{ false }; - bool delay_frontier_confirmation_height_updating{ false }; bool read_only{ false }; size_t sideband_batch_size{ 512 }; size_t block_processor_batch_size{ 0 }; diff --git a/nano/node/wallet.cpp b/nano/node/wallet.cpp index d8df2085..231e052d 100644 --- a/nano/node/wallet.cpp +++ b/nano/node/wallet.cpp @@ -808,12 +808,12 @@ nano::public_key nano::wallet::deterministic_insert (nano::transaction const & t { work_ensure (key, key); } + auto half_principal_weight (wallets.node.minimum_principal_weight () / 2); auto block_transaction (wallets.node.store.tx_begin_read ()); - if (wallets.node.ledger.weight (block_transaction, key) >= wallets.node.config.vote_minimum.number ()) + if (wallets.check_rep (block_transaction, key, half_principal_weight)) { std::lock_guard lock (representatives_mutex); representatives.insert (key); - ++wallets.reps_count; } } return key; @@ -852,11 +852,11 @@ nano::public_key nano::wallet::insert_adhoc (nano::transaction const & transacti { work_ensure (key, wallets.node.ledger.latest_root (block_transaction, key)); } - if (wallets.node.ledger.weight (block_transaction, key) >= wallets.node.config.vote_minimum.number ()) + auto half_principal_weight (wallets.node.minimum_principal_weight () / 2); + if (wallets.check_rep (block_transaction, key, half_principal_weight)) { std::lock_guard lock (representatives_mutex); representatives.insert (key); - ++wallets.reps_count; } } return key; @@ -1864,10 +1864,28 @@ void nano::wallets::clear_send_ids (nano::transaction const & transaction_a) assert (status == 0); } +bool nano::wallets::check_rep (nano::transaction const & transaction_a, nano::account const & account_a, nano::uint128_t const & half_principal_weight_a) +{ + bool result (false); + auto weight (node.ledger.weight (transaction_a, account_a)); + if (weight >= node.config.vote_minimum.number ()) + { + result = true; + ++reps_count; + if (weight >= half_principal_weight_a) + { + ++half_principal_reps_count; + } + } + return result; +} + void nano::wallets::compute_reps () { std::lock_guard lock (mutex); reps_count = 0; + half_principal_reps_count = 0; + auto half_principal_weight (node.minimum_principal_weight () / 2); auto ledger_transaction (node.store.tx_begin_read ()); auto transaction (tx_begin_read ()); for (auto i (items.begin ()), n (items.end ()); i != n; ++i) @@ -1877,10 +1895,9 @@ void nano::wallets::compute_reps () for (auto ii (wallet.store.begin (transaction)), nn (wallet.store.end ()); ii != nn; ++ii) { auto account (ii->first); - if (node.ledger.weight (ledger_transaction, account) >= node.config.vote_minimum.number ()) + if (check_rep (ledger_transaction, account, half_principal_weight)) { representatives_l.insert (account); - ++reps_count; } } std::lock_guard representatives_lock (wallet.representatives_mutex); diff --git a/nano/node/wallet.hpp b/nano/node/wallet.hpp index 8de2ba66..bda36377 100644 --- a/nano/node/wallet.hpp +++ b/nano/node/wallet.hpp @@ -199,6 +199,7 @@ public: bool exists (nano::transaction const &, nano::public_key const &); void stop (); void clear_send_ids (nano::transaction const &); + bool check_rep (nano::transaction const &, nano::account const &, nano::uint128_t const &); void compute_reps (); void ongoing_compute_reps (); void split_if_needed (nano::transaction &, nano::block_store &); @@ -221,6 +222,7 @@ public: static nano::uint128_t const generate_priority; static nano::uint128_t const high_priority; std::atomic reps_count{ 0 }; + std::atomic half_principal_reps_count{ 0 }; // Representatives with at least 50% of principal representative requirements /** Start read-write transaction */ nano::write_transaction tx_begin_write (); diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index 8115b8ff..7aa0c06d 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -5863,9 +5863,9 @@ TEST (rpc, confirmation_height_currently_processing) { // The chains should be longer than the batch_write_size to test the amount of blocks confirmed is correct. nano::system system; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node = system.add_node (nano::node_config (24000, system.logging), node_flags); + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node = system.add_node (node_config); system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); // Do enough blocks to reliably call RPC before the confirmation height has finished diff --git a/nano/slow_test/node.cpp b/nano/slow_test/node.cpp index c3c22b45..7bf4b5f2 100644 --- a/nano/slow_test/node.cpp +++ b/nano/slow_test/node.cpp @@ -462,9 +462,8 @@ TEST (confirmation_height, many_accounts_single_confirmation) nano::system system; nano::node_config node_config (24000, system.logging); node_config.online_weight_minimum = 100; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node = system.add_node (node_config, node_flags); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node = system.add_node (node_config); system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); // As this test can take a while extend the next frontier check @@ -534,9 +533,8 @@ TEST (confirmation_height, many_accounts_many_confirmations) nano::system system; nano::node_config node_config (24000, system.logging); node_config.online_weight_minimum = 100; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node = system.add_node (node_config, node_flags); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node = system.add_node (node_config); system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); // As this test can take a while extend the next frontier check @@ -580,9 +578,9 @@ TEST (confirmation_height, many_accounts_many_confirmations) TEST (confirmation_height, long_chains) { nano::system system; - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node = system.add_node (nano::node_config (24000, system.logging), node_flags); + nano::node_config node_config (24000, system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node = system.add_node (node_config); nano::keypair key1; system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); nano::block_hash latest (node->latest (nano::test_genesis_key.pub)); @@ -673,9 +671,8 @@ TEST (confirmation_height, prioritize_frontiers_overwrite) { nano::system system; nano::node_config node_config (24000, system.logging); - nano::node_flags node_flags; - node_flags.delay_frontier_confirmation_height_updating = true; - auto node = system.add_node (node_config, node_flags); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto node = system.add_node (node_config); system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); // As this test can take a while extend the next frontier check