Skip to content

Commit

Permalink
Fix race between election activation and confirmation_heigh_processor
Browse files Browse the repository at this point in the history
A block that is being processed by the confirmation_heigh_processor should not be inserted into the AEC
  • Loading branch information
gr0vity-dev committed Feb 5, 2024
1 parent 647c3c4 commit ea9411e
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 1 deletion.
2 changes: 1 addition & 1 deletion nano/node/active_transactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ nano::election_insertion_result nano::active_transactions::insert (std::shared_p
auto const existing = roots.get<tag_root> ().find (root);
if (existing == roots.get<tag_root> ().end ())
{
if (!recently_confirmed.exists (root))
if (!recently_confirmed.exists (root) && !node.confirmation_height_processor.is_processing_or_confirmed (hash))
{
result.inserted = true;
auto observe_rep_cb = [&node = node] (auto const & rep_a) {
Expand Down
5 changes: 5 additions & 0 deletions nano/node/confirmation_height_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,11 @@ bool nano::confirmation_height_processor::is_processing_block (nano::block_hash
return is_processing_added_block (hash_a) || unbounded_processor.has_iterated_over_block (hash_a);
}

bool nano::confirmation_height_processor::is_processing_or_confirmed (nano::block_hash const & hash_a) const
{
return is_processing_added_block (hash_a) || unbounded_processor.has_iterated_or_confirmed (hash_a);
}

nano::block_hash nano::confirmation_height_processor::current () const
{
nano::lock_guard<nano::mutex> lk (mutex);
Expand Down
1 change: 1 addition & 0 deletions nano/node/confirmation_height_processor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class confirmation_height_processor final
std::size_t awaiting_processing_size () const;
bool is_processing_added_block (nano::block_hash const & hash_a) const;
bool is_processing_block (nano::block_hash const &) const;
bool is_processing_or_confirmed (nano::block_hash const &) const;
nano::block_hash current () const;

/*
Expand Down
28 changes: 28 additions & 0 deletions nano/node/confirmation_height_unbounded.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,19 @@ void nano::confirmation_height_unbounded::clear_process_vars ()
implicit_receive_cemented_mapping_size = 0;
{
nano::lock_guard<nano::mutex> guard (block_cache_mutex);
// Move the hashes from block_cache to recently_confirmed
for (const auto & pair : block_cache)
{
const auto & block_hash = pair.first;
recently_confirmed.push_back (block_hash);
}
block_cache.clear ();

// Ensure recently_confirmed doesn't exceed max_recently_confirmed
while (recently_confirmed.size () > max_recently_confirmed)
{
recently_confirmed.pop_front ();
}
}
}

Expand All @@ -469,6 +481,22 @@ bool nano::confirmation_height_unbounded::has_iterated_over_block (nano::block_h
return block_cache.count (hash_a) == 1;
}

bool nano::confirmation_height_unbounded::is_recently_confirmed (nano::block_hash const & hash_a) const
{
nano::lock_guard<nano::mutex> guard (block_cache_mutex);
auto result = std::find (recently_confirmed.begin (), recently_confirmed.end (), hash_a) != recently_confirmed.end ();
return result;
}

bool nano::confirmation_height_unbounded::has_iterated_or_confirmed (nano::block_hash const & hash_a) const
{
nano::lock_guard<nano::mutex> guard (block_cache_mutex);
bool iterated_over = block_cache.count (hash_a) == 1;
bool recently_confirmed_status = std::find (recently_confirmed.begin (), recently_confirmed.end (), hash_a) != recently_confirmed.end ();
// Return true if either condition is met
return iterated_over || recently_confirmed_status;
}

uint64_t nano::confirmation_height_unbounded::block_cache_size () const
{
nano::lock_guard<nano::mutex> guard (block_cache_mutex);
Expand Down
4 changes: 4 additions & 0 deletions nano/node/confirmation_height_unbounded.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class confirmation_height_unbounded final
void process (std::shared_ptr<nano::block> original_block);
void cement_blocks (nano::write_guard &);
bool has_iterated_over_block (nano::block_hash const &) const;
bool is_recently_confirmed (nano::block_hash const &) const;
bool has_iterated_or_confirmed (nano::block_hash const &) const;

private:
class confirmed_iterated_pair
Expand Down Expand Up @@ -74,6 +76,8 @@ class confirmation_height_unbounded final
mutable nano::mutex block_cache_mutex;
std::unordered_map<nano::block_hash, std::shared_ptr<nano::block>> block_cache;
uint64_t block_cache_size () const;
static constexpr size_t max_recently_confirmed = 65536;
std::deque<nano::block_hash> recently_confirmed;

nano::timer<std::chrono::milliseconds> timer;

Expand Down

0 comments on commit ea9411e

Please sign in to comment.