Inactive votes cache confirmation status (#2553)
* Adding separate confirmation status / bootstrap status for inactive votes cache (it can be different with disabled lazy bootstrap using config bootstrap_fraction_numerator) * Apply reviews * Inactive vote cache item can be confirmed with single vote in tests * Add test to prevent confirmation without quorum
This commit is contained in:
parent
298a3c8915
commit
81c82d88ea
3 changed files with 78 additions and 11 deletions
|
|
@ -481,6 +481,65 @@ TEST (bootstrap_processor, frontiers_confirmed)
|
|||
ASSERT_EQ (0, node2->stats.count (nano::stat::type::bootstrap, nano::stat::detail::frontier_confirmation_failed, nano::stat::dir::in));
|
||||
}
|
||||
|
||||
TEST (bootstrap_processor, frontiers_unconfirmed_threshold)
|
||||
{
|
||||
nano::system system;
|
||||
nano::node_config node_config (nano::get_available_port (), system.logging);
|
||||
node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
|
||||
node_config.tcp_io_timeout = std::chrono::seconds (2);
|
||||
node_config.bootstrap_fraction_numerator = 4;
|
||||
nano::node_flags node_flags;
|
||||
node_flags.disable_bootstrap_bulk_pull_server = true;
|
||||
node_flags.disable_bootstrap_bulk_push_client = true;
|
||||
node_flags.disable_legacy_bootstrap = true;
|
||||
node_flags.disable_lazy_bootstrap = true;
|
||||
node_flags.disable_wallet_bootstrap = true;
|
||||
node_flags.disable_rep_crawler = true;
|
||||
auto node1 = system.add_node (node_config, node_flags);
|
||||
nano::genesis genesis;
|
||||
nano::keypair key1, key2;
|
||||
// Generating invalid chain
|
||||
auto threshold (node1->gap_cache.bootstrap_threshold () + 1);
|
||||
ASSERT_LT (threshold, node1->config.online_weight_minimum.number ());
|
||||
auto send1 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - threshold, key1.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (genesis.hash ())));
|
||||
ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code);
|
||||
auto send2 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, send1->hash (), nano::test_genesis_key.pub, nano::genesis_amount - threshold - nano::Gxrb_ratio, key2.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (send1->hash ())));
|
||||
ASSERT_EQ (nano::process_result::progress, node1->process (*send2).code);
|
||||
auto open1 (std::make_shared<nano::state_block> (key1.pub, 0, key1.pub, threshold, send1->hash (), key1.prv, key1.pub, *system.work.generate (key1.pub)));
|
||||
ASSERT_EQ (nano::process_result::progress, node1->process (*open1).code);
|
||||
auto open2 (std::make_shared<nano::state_block> (key2.pub, 0, key2.pub, nano::Gxrb_ratio, send2->hash (), key2.prv, key2.pub, *system.work.generate (key2.pub)));
|
||||
ASSERT_EQ (nano::process_result::progress, node1->process (*open2).code);
|
||||
system.wallet (0)->insert_adhoc (key1.prv); // Small representative
|
||||
|
||||
// Test node with large representative
|
||||
node_config.peering_port = nano::get_available_port ();
|
||||
auto node2 = system.add_node (node_config, node_flags);
|
||||
system.wallet (1)->insert_adhoc (nano::test_genesis_key.prv);
|
||||
|
||||
// Test node to bootstrap
|
||||
node_config.peering_port = nano::get_available_port ();
|
||||
node_flags.disable_legacy_bootstrap = false;
|
||||
node_flags.disable_rep_crawler = false;
|
||||
auto node3 = system.add_node (node_config, node_flags);
|
||||
ASSERT_EQ (nano::process_result::progress, node3->process (*send1).code);
|
||||
ASSERT_EQ (nano::process_result::progress, node3->process (*open1).code); // Change known representative weight
|
||||
system.deadline_set (5s);
|
||||
while (node3->rep_crawler.representative_count () < 2)
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
node3->bootstrap_initiator.bootstrap (node1->network.endpoint ());
|
||||
system.deadline_set (15s);
|
||||
while (node3->stats.count (nano::stat::type::bootstrap, nano::stat::detail::frontier_confirmation_failed, nano::stat::dir::in) < 1)
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
ASSERT_FALSE (node3->ledger.block_exists (send2->hash ()));
|
||||
ASSERT_FALSE (node3->ledger.block_exists (open2->hash ()));
|
||||
ASSERT_EQ (1, node3->stats.count (nano::stat::type::bootstrap, nano::stat::detail::frontier_confirmation_failed, nano::stat::dir::in)); // failed confirmation
|
||||
ASSERT_EQ (0, node3->stats.count (nano::stat::type::bootstrap, nano::stat::detail::frontier_confirmation_successful, nano::stat::dir::in));
|
||||
}
|
||||
|
||||
TEST (bootstrap_processor, push_diamond)
|
||||
{
|
||||
nano::system system;
|
||||
|
|
|
|||
|
|
@ -997,7 +997,7 @@ void nano::active_transactions::add_inactive_votes_cache (nano::block_hash const
|
|||
{
|
||||
auto & inactive_by_hash (inactive_votes_cache.get<tag_hash> ());
|
||||
auto existing (inactive_by_hash.find (hash_a));
|
||||
if (existing != inactive_by_hash.end () && !existing->confirmed)
|
||||
if (existing != inactive_by_hash.end () && (!existing->confirmed || !existing->bootstrap_started))
|
||||
{
|
||||
auto is_new (false);
|
||||
inactive_by_hash.modify (existing, [representative_a, &is_new](nano::inactive_cache_information & info) {
|
||||
|
|
@ -1012,7 +1012,14 @@ void nano::active_transactions::add_inactive_votes_cache (nano::block_hash const
|
|||
|
||||
if (is_new)
|
||||
{
|
||||
if (inactive_votes_bootstrap_check (existing->voters, hash_a))
|
||||
bool confirmed (false);
|
||||
if (inactive_votes_bootstrap_check (existing->voters, hash_a, confirmed) && !existing->bootstrap_started)
|
||||
{
|
||||
inactive_by_hash.modify (existing, [](nano::inactive_cache_information & info) {
|
||||
info.bootstrap_started = true;
|
||||
});
|
||||
}
|
||||
if (confirmed && !existing->confirmed)
|
||||
{
|
||||
inactive_by_hash.modify (existing, [](nano::inactive_cache_information & info) {
|
||||
info.confirmed = true;
|
||||
|
|
@ -1023,8 +1030,10 @@ void nano::active_transactions::add_inactive_votes_cache (nano::block_hash const
|
|||
else
|
||||
{
|
||||
std::vector<nano::account> representative_vector (1, representative_a);
|
||||
bool confirmed (false);
|
||||
bool start_bootstrap (inactive_votes_bootstrap_check (representative_vector, hash_a, confirmed));
|
||||
auto & inactive_by_arrival (inactive_votes_cache.get<tag_arrival> ());
|
||||
inactive_by_arrival.emplace (nano::inactive_cache_information{ std::chrono::steady_clock::now (), hash_a, representative_vector });
|
||||
inactive_by_arrival.emplace (nano::inactive_cache_information{ std::chrono::steady_clock::now (), hash_a, representative_vector, start_bootstrap, confirmed });
|
||||
if (inactive_votes_cache.size () > inactive_votes_cache_max)
|
||||
{
|
||||
inactive_by_arrival.erase (inactive_by_arrival.begin ());
|
||||
|
|
@ -1057,7 +1066,7 @@ void nano::active_transactions::erase_inactive_votes_cache (nano::block_hash con
|
|||
}
|
||||
}
|
||||
|
||||
bool nano::active_transactions::inactive_votes_bootstrap_check (std::vector<nano::account> const & voters_a, nano::block_hash const & hash_a)
|
||||
bool nano::active_transactions::inactive_votes_bootstrap_check (std::vector<nano::account> const & voters_a, nano::block_hash const & hash_a, bool & confirmed_a)
|
||||
{
|
||||
uint128_t tally;
|
||||
for (auto const & voter : voters_a)
|
||||
|
|
@ -1065,12 +1074,10 @@ bool nano::active_transactions::inactive_votes_bootstrap_check (std::vector<nano
|
|||
tally += node.ledger.weight (voter);
|
||||
}
|
||||
bool start_bootstrap (false);
|
||||
if (!node.flags.disable_lazy_bootstrap)
|
||||
if (tally >= node.config.online_weight_minimum.number ())
|
||||
{
|
||||
if (tally >= node.config.online_weight_minimum.number ())
|
||||
{
|
||||
start_bootstrap = true;
|
||||
}
|
||||
start_bootstrap = true;
|
||||
confirmed_a = true;
|
||||
}
|
||||
else if (!node.flags.disable_legacy_bootstrap && tally > node.gap_cache.bootstrap_threshold ())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ public:
|
|||
std::chrono::steady_clock::time_point arrival;
|
||||
nano::block_hash hash;
|
||||
std::vector<nano::account> voters;
|
||||
bool confirmed{ false };
|
||||
bool bootstrap_started{ false };
|
||||
bool confirmed{ false }; // Did item reach votes quorum? (minimum config value)
|
||||
};
|
||||
|
||||
// Core class for determining consensus
|
||||
|
|
@ -205,7 +206,7 @@ private:
|
|||
ordered_cache inactive_votes_cache;
|
||||
// clang-format on
|
||||
static size_t constexpr inactive_votes_cache_max{ 16 * 1024 };
|
||||
bool inactive_votes_bootstrap_check (std::vector<nano::account> const &, nano::block_hash const &);
|
||||
bool inactive_votes_bootstrap_check (std::vector<nano::account> const &, nano::block_hash const &, bool &);
|
||||
// clang-format off
|
||||
boost::multi_index_container<nano::election_timepoint,
|
||||
mi::indexed_by<
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue