Add frontiers confirmation modes (#2175)

always - always algressive confirm frontiers
automatic - confirm frontiers in always mode if node contains representative with at least 50% of principal weight, confirm frontiers less often otherwise
disabled - do not confirm frontiers

* Use node::minimum_principal_weight ()
* More agressive settings for wallets accounts prioritization
* Update node.rep_self_vote test
* Update TOML config
This commit is contained in:
Sergey Kroshnin 2019-08-26 12:17:59 +03:00 committed by GitHub
commit 2f7e6c280e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 243 additions and 95 deletions

View file

@ -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;

View file

@ -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<nano::send_block> (genesis.hash (), key1.pub, nano::genesis_amount - nano::xrb_ratio, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));

View file

@ -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<nano::uint128_t>::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<nano::send_block> (genesis.hash (), key1.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));

View file

@ -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));

View file

@ -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<nano::uint128_t>::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::state_block> (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<nano::account, num_accounts>{ 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<std::mutex> 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;

View file

@ -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);
}

View file

@ -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::mutex> &
std::deque<std::shared_ptr<nano::block>> rebroadcast_bundle;
std::deque<std::pair<std::shared_ptr<nano::block>, std::shared_ptr<std::vector<std::shared_ptr<nano::transport::channel>>>>> 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<std::mutex> 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

View file

@ -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<double> ("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<std::string> ("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 ());

View file

@ -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 };

View file

@ -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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> representatives_lock (wallet.representatives_mutex);

View file

@ -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<uint64_t> reps_count{ 0 };
std::atomic<uint64_t> half_principal_reps_count{ 0 }; // Representatives with at least 50% of principal representative requirements
/** Start read-write transaction */
nano::write_transaction tx_begin_write ();

View file

@ -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

View file

@ -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