Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inactive votes cache confirmation status #2553

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
387ee32
Separate inactive votes cache from gap cache
SergiySW Feb 7, 2020
7fd5854
Apply review
SergiySW Feb 7, 2020
cbde5bc
Merge remote-tracking branch 'upstream/develop' into active/inactive_…
SergiySW Feb 7, 2020
ef4a984
Use shortened boost::multi_index
SergiySW Feb 7, 2020
9def9c6
Faster erase
SergiySW Feb 8, 2020
2d21783
Merge remote-tracking branch 'upstream/develop' into active/inactive_…
SergiySW Feb 11, 2020
c05b982
Move functional change to new PR
SergiySW Feb 11, 2020
0cc6d12
Correct confirmation status for inactive votes cache
SergiySW Feb 11, 2020
d36bdd0
Add confirmed status for bootstrap
SergiySW Feb 11, 2020
289bc9d
Merge branch 'active/inactive_votes_cache_split' into active/inactive…
SergiySW Feb 11, 2020
dca8be3
Correct confirmed status
SergiySW Feb 11, 2020
c4a23fb
Merge remote-tracking branch 'upstream/develop' into active/inactive_…
SergiySW Feb 11, 2020
8387588
Inactive vote cache item can be confirmed with single vote in tests
SergiySW Feb 12, 2020
48f5034
Merge branch 'active/inactive_votes_cache_split' into active/inactive…
SergiySW Feb 12, 2020
fdc7927
Update branch with inactive_votes_cache_split changes
SergiySW Feb 12, 2020
8b66b13
Add test to prevent confirmation without quorum
SergiySW Feb 12, 2020
3cc378f
Merge remote-tracking branch 'upstream/develop' into active/inactive_…
SergiySW Feb 12, 2020
b232b5b
Merge branch 'active/inactive_votes_cache_split' into active/inactive…
SergiySW Feb 12, 2020
979ceac
Guilherme review: remove functional change
SergiySW Feb 12, 2020
dd04b58
Merge branch 'active/inactive_votes_cache_split' into active/inactive…
SergiySW Feb 12, 2020
24cd250
Single bool in inactive_cache_information
SergiySW Feb 12, 2020
fffc60f
Merge branch 'active/inactive_votes_cache_split' into active/inactive…
SergiySW Feb 12, 2020
6ea7371
Update header with comments
SergiySW Feb 12, 2020
4f49e5f
Merge remote-tracking branch 'upstream/develop' into active/inactive_…
SergiySW Feb 13, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions nano/core_test/bootstrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
25 changes: 16 additions & 9 deletions nano/node/active_transactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
Expand All @@ -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 ());
Expand Down Expand Up @@ -1057,20 +1066,18 @@ 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)
{
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 ())
{
Expand Down
5 changes: 3 additions & 2 deletions nano/node/active_transactions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ class inactive_cache_information final
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
Expand Down Expand Up @@ -205,7 +206,7 @@ class active_transactions final
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<
Expand Down