Separate inactive votes cache from gap cache (#2542)
* Separate inactive votes cache from gap cache * Move functional changes to new PR
This commit is contained in:
parent
6e5c0ca16b
commit
298a3c8915
5 changed files with 96 additions and 24 deletions
|
|
@ -995,11 +995,12 @@ void nano::active_transactions::add_inactive_votes_cache (nano::block_hash const
|
|||
// Check principal representative status
|
||||
if (node.ledger.weight (representative_a) > node.minimum_principal_weight ())
|
||||
{
|
||||
auto existing (inactive_votes_cache.get<nano::gap_cache::tag_hash> ().find (hash_a));
|
||||
if (existing != inactive_votes_cache.get<nano::gap_cache::tag_hash> ().end () && !existing->confirmed)
|
||||
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)
|
||||
{
|
||||
auto is_new (false);
|
||||
inactive_votes_cache.get<nano::gap_cache::tag_hash> ().modify (existing, [representative_a, &is_new](nano::gap_information & info) {
|
||||
inactive_by_hash.modify (existing, [representative_a, &is_new](nano::inactive_cache_information & info) {
|
||||
auto it = std::find (info.voters.begin (), info.voters.end (), representative_a);
|
||||
is_new = (it == info.voters.end ());
|
||||
if (is_new)
|
||||
|
|
@ -1011,9 +1012,9 @@ void nano::active_transactions::add_inactive_votes_cache (nano::block_hash const
|
|||
|
||||
if (is_new)
|
||||
{
|
||||
if (node.gap_cache.bootstrap_check (existing->voters, hash_a))
|
||||
if (inactive_votes_bootstrap_check (existing->voters, hash_a))
|
||||
{
|
||||
inactive_votes_cache.get<nano::gap_cache::tag_hash> ().modify (existing, [](nano::gap_information & info) {
|
||||
inactive_by_hash.modify (existing, [](nano::inactive_cache_information & info) {
|
||||
info.confirmed = true;
|
||||
});
|
||||
}
|
||||
|
|
@ -1021,37 +1022,86 @@ void nano::active_transactions::add_inactive_votes_cache (nano::block_hash const
|
|||
}
|
||||
else
|
||||
{
|
||||
inactive_votes_cache.get<nano::gap_cache::tag_arrival> ().emplace (nano::gap_information{ std::chrono::steady_clock::now (), hash_a, std::vector<nano::account> (1, representative_a) });
|
||||
std::vector<nano::account> representative_vector (1, representative_a);
|
||||
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 });
|
||||
if (inactive_votes_cache.size () > inactive_votes_cache_max)
|
||||
{
|
||||
inactive_votes_cache.get<nano::gap_cache::tag_arrival> ().erase (inactive_votes_cache.get<nano::gap_cache::tag_arrival> ().begin ());
|
||||
inactive_by_arrival.erase (inactive_by_arrival.begin ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nano::gap_information nano::active_transactions::find_inactive_votes_cache (nano::block_hash const & hash_a)
|
||||
nano::inactive_cache_information nano::active_transactions::find_inactive_votes_cache (nano::block_hash const & hash_a)
|
||||
{
|
||||
auto existing (inactive_votes_cache.get<nano::gap_cache::tag_hash> ().find (hash_a));
|
||||
if (existing != inactive_votes_cache.get<nano::gap_cache::tag_hash> ().end ())
|
||||
auto & inactive_by_hash (inactive_votes_cache.get<tag_hash> ());
|
||||
auto existing (inactive_by_hash.find (hash_a));
|
||||
if (existing != inactive_by_hash.end ())
|
||||
{
|
||||
return *existing;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nano::gap_information{ std::chrono::steady_clock::time_point{}, 0, std::vector<nano::account>{} };
|
||||
return nano::inactive_cache_information{ std::chrono::steady_clock::time_point{}, 0, std::vector<nano::account>{} };
|
||||
}
|
||||
}
|
||||
|
||||
void nano::active_transactions::erase_inactive_votes_cache (nano::block_hash const & hash_a)
|
||||
{
|
||||
auto existing (inactive_votes_cache.get<nano::gap_cache::tag_hash> ().find (hash_a));
|
||||
if (existing != inactive_votes_cache.get<nano::gap_cache::tag_hash> ().end ())
|
||||
auto & inactive_by_hash (inactive_votes_cache.get<tag_hash> ());
|
||||
auto existing (inactive_by_hash.find (hash_a));
|
||||
if (existing != inactive_by_hash.end ())
|
||||
{
|
||||
inactive_votes_cache.get<nano::gap_cache::tag_hash> ().erase (existing);
|
||||
inactive_by_hash.erase (existing);
|
||||
}
|
||||
}
|
||||
|
||||
bool nano::active_transactions::inactive_votes_bootstrap_check (std::vector<nano::account> const & voters_a, nano::block_hash const & hash_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 ())
|
||||
{
|
||||
start_bootstrap = true;
|
||||
}
|
||||
}
|
||||
else if (!node.flags.disable_legacy_bootstrap && tally > node.gap_cache.bootstrap_threshold ())
|
||||
{
|
||||
start_bootstrap = true;
|
||||
}
|
||||
if (start_bootstrap)
|
||||
{
|
||||
auto node_l (node.shared ());
|
||||
auto now (std::chrono::steady_clock::now ());
|
||||
node.alarm.add (node_l->network_params.network.is_test_network () ? now + std::chrono::milliseconds (5) : now + std::chrono::seconds (5), [node_l, hash_a]() {
|
||||
auto transaction (node_l->store.tx_begin_read ());
|
||||
if (!node_l->store.block_exists (transaction, hash_a))
|
||||
{
|
||||
if (!node_l->bootstrap_initiator.in_progress ())
|
||||
{
|
||||
node_l->logger.try_log (boost::str (boost::format ("Missing block %1% which has enough votes to warrant lazy bootstrapping it") % hash_a.to_string ()));
|
||||
}
|
||||
if (!node_l->flags.disable_lazy_bootstrap)
|
||||
{
|
||||
node_l->bootstrap_initiator.bootstrap_lazy (hash_a);
|
||||
}
|
||||
else if (!node_l->flags.disable_legacy_bootstrap)
|
||||
{
|
||||
node_l->bootstrap_initiator.bootstrap ();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return start_bootstrap;
|
||||
}
|
||||
|
||||
size_t nano::active_transactions::dropped_elections_cache_size ()
|
||||
{
|
||||
nano::lock_guard<std::mutex> guard (mutex);
|
||||
|
|
|
|||
|
|
@ -60,6 +60,15 @@ public:
|
|||
nano::qualified_root root;
|
||||
};
|
||||
|
||||
class inactive_cache_information final
|
||||
{
|
||||
public:
|
||||
std::chrono::steady_clock::time_point arrival;
|
||||
nano::block_hash hash;
|
||||
std::vector<nano::account> voters;
|
||||
bool confirmed{ false };
|
||||
};
|
||||
|
||||
// Core class for determining consensus
|
||||
// Holds all active blocks i.e. recently added blocks that need confirmation
|
||||
class active_transactions final
|
||||
|
|
@ -70,6 +79,8 @@ class active_transactions final
|
|||
class tag_root {};
|
||||
class tag_sequence {};
|
||||
class tag_uncemented {};
|
||||
class tag_arrival {};
|
||||
class tag_hash {};
|
||||
// clang-format on
|
||||
|
||||
public:
|
||||
|
|
@ -114,7 +125,7 @@ public:
|
|||
std::deque<nano::election_status> confirmed;
|
||||
void add_confirmed (nano::election_status const &, nano::qualified_root const &);
|
||||
void add_inactive_votes_cache (nano::block_hash const &, nano::account const &);
|
||||
nano::gap_information find_inactive_votes_cache (nano::block_hash const &);
|
||||
nano::inactive_cache_information find_inactive_votes_cache (nano::block_hash const &);
|
||||
void erase_inactive_votes_cache (nano::block_hash const &);
|
||||
nano::confirmation_height_processor & confirmation_height_processor;
|
||||
nano::node & node;
|
||||
|
|
@ -184,8 +195,17 @@ private:
|
|||
void prioritize_account_for_confirmation (prioritize_num_uncemented &, size_t &, nano::account const &, nano::account_info const &, uint64_t);
|
||||
static size_t constexpr max_priority_cementable_frontiers{ 100000 };
|
||||
static size_t constexpr confirmed_frontiers_max_pending_cut_off{ 1000 };
|
||||
nano::gap_cache::ordered_gaps inactive_votes_cache;
|
||||
// clang-format off
|
||||
using ordered_cache = boost::multi_index_container<nano::inactive_cache_information,
|
||||
mi::indexed_by<
|
||||
mi::ordered_non_unique<mi::tag<tag_arrival>,
|
||||
mi::member<nano::inactive_cache_information, std::chrono::steady_clock::time_point, &nano::inactive_cache_information::arrival>>,
|
||||
mi::hashed_unique<mi::tag<tag_hash>,
|
||||
mi::member<nano::inactive_cache_information, nano::block_hash, &nano::inactive_cache_information::hash>>>>;
|
||||
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 &);
|
||||
// clang-format off
|
||||
boost::multi_index_container<nano::election_timepoint,
|
||||
mi::indexed_by<
|
||||
|
|
|
|||
|
|
@ -754,8 +754,9 @@ bool nano::bootstrap_attempt::confirm_frontiers (nano::unique_lock<std::mutex> &
|
|||
}
|
||||
else
|
||||
{
|
||||
nano::lock_guard<std::mutex> active_lock (node->active.mutex);
|
||||
nano::unique_lock<std::mutex> active_lock (node->active.mutex);
|
||||
auto existing (node->active.find_inactive_votes_cache (*ii));
|
||||
active_lock.unlock ();
|
||||
nano::uint128_t tally;
|
||||
for (auto & voter : existing.voters)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,11 +40,12 @@ void nano::gap_cache::vote (std::shared_ptr<nano::vote> vote_a)
|
|||
nano::lock_guard<std::mutex> lock (mutex);
|
||||
for (auto hash : *vote_a)
|
||||
{
|
||||
auto existing (blocks.get<tag_hash> ().find (hash));
|
||||
if (existing != blocks.get<tag_hash> ().end () && !existing->confirmed)
|
||||
auto & gap_blocks_by_hash (blocks.get<tag_hash> ());
|
||||
auto existing (gap_blocks_by_hash.find (hash));
|
||||
if (existing != gap_blocks_by_hash.end () && !existing->bootstrap_started)
|
||||
{
|
||||
auto is_new (false);
|
||||
blocks.get<tag_hash> ().modify (existing, [&is_new, &vote_a](nano::gap_information & info) {
|
||||
gap_blocks_by_hash.modify (existing, [&is_new, &vote_a](nano::gap_information & info) {
|
||||
auto it = std::find (info.voters.begin (), info.voters.end (), vote_a->account);
|
||||
is_new = (it == info.voters.end ());
|
||||
if (is_new)
|
||||
|
|
@ -57,8 +58,8 @@ void nano::gap_cache::vote (std::shared_ptr<nano::vote> vote_a)
|
|||
{
|
||||
if (bootstrap_check (existing->voters, hash))
|
||||
{
|
||||
blocks.get<tag_hash> ().modify (existing, [](nano::gap_information & info) {
|
||||
info.confirmed = true;
|
||||
gap_blocks_by_hash.modify (existing, [](nano::gap_information & info) {
|
||||
info.bootstrap_started = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -69,7 +70,7 @@ void nano::gap_cache::vote (std::shared_ptr<nano::vote> vote_a)
|
|||
bool nano::gap_cache::bootstrap_check (std::vector<nano::account> const & voters_a, nano::block_hash const & hash_a)
|
||||
{
|
||||
uint128_t tally;
|
||||
for (auto & voter : voters_a)
|
||||
for (auto const & voter : voters_a)
|
||||
{
|
||||
tally += node.ledger.weight (voter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public:
|
|||
std::chrono::steady_clock::time_point arrival;
|
||||
nano::block_hash hash;
|
||||
std::vector<nano::account> voters;
|
||||
bool confirmed{ false };
|
||||
bool bootstrap_started{ false };
|
||||
};
|
||||
|
||||
/** Maintains voting and arrival information for gaps (missing source or previous blocks in account chains) */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue