From 2f24a98bb8d52f5441714c058892cb27ef90a0ee Mon Sep 17 00:00:00 2001 From: Colin LeMahieu Date: Sat, 23 Mar 2024 18:40:57 +0000 Subject: [PATCH] Remove confirmation_height_processor and rename usages to confirming_set. --- CMakeLists.txt | 1 - nano/core_test/active_transactions.cpp | 2 +- nano/core_test/confirming_set.cpp | 4 +- nano/core_test/node.cpp | 2 +- nano/core_test/request_aggregator.cpp | 4 +- nano/lib/locks.cpp | 4 +- nano/lib/locks.hpp | 1 - nano/nano_node/entry.cpp | 2 +- nano/node/CMakeLists.txt | 6 - nano/node/active_transactions.cpp | 10 +- nano/node/active_transactions.hpp | 2 +- nano/node/confirmation_height_bounded.cpp | 580 -------------------- nano/node/confirmation_height_bounded.hpp | 135 ----- nano/node/confirmation_height_processor.cpp | 225 -------- nano/node/confirmation_height_processor.hpp | 113 ---- nano/node/confirmation_height_unbounded.cpp | 498 ----------------- nano/node/confirmation_height_unbounded.hpp | 114 ---- nano/node/json_handler.cpp | 2 +- nano/node/node.cpp | 12 +- nano/node/node.hpp | 4 +- nano/node/wallet.cpp | 2 +- nano/rpc_test/rpc.cpp | 2 +- nano/secure/common.hpp | 7 - nano/slow_test/node.cpp | 16 +- 24 files changed, 33 insertions(+), 1715 deletions(-) delete mode 100644 nano/node/confirmation_height_bounded.cpp delete mode 100644 nano/node/confirmation_height_bounded.hpp delete mode 100644 nano/node/confirmation_height_processor.cpp delete mode 100644 nano/node/confirmation_height_processor.hpp delete mode 100644 nano/node/confirmation_height_unbounded.cpp delete mode 100644 nano/node/confirmation_height_unbounded.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c411cee1..10d92541 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,7 +97,6 @@ set_property( block_arrival block_processor block_uniquer - confirmation_height_processor dropped_elections, election_winner_details gap_cache diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index 4360d1f2..734eeeb7 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -1244,7 +1244,7 @@ TEST (active_transactions, activate_inactive) ASSERT_NE (nullptr, election); election->force_confirm (); - ASSERT_TIMELY (5s, !node.confirmation_height_processor.exists (send2->hash ())); + ASSERT_TIMELY (5s, !node.confirming_set.exists (send2->hash ())); ASSERT_TIMELY (5s, node.block_confirmed (send2->hash ())); ASSERT_TIMELY (5s, node.block_confirmed (send->hash ())); diff --git a/nano/core_test/confirming_set.cpp b/nano/core_test/confirming_set.cpp index 6050d437..d7137eb5 100644 --- a/nano/core_test/confirming_set.cpp +++ b/nano/core_test/confirming_set.cpp @@ -103,7 +103,7 @@ TEST (confirmation_callback, observer_callbacks) ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send1)); } - node->confirmation_height_processor.add (send1->hash ()); + node->confirming_set.add (send1->hash ()); // Callback is performed for all blocks that are confirmed ASSERT_TIMELY_EQ (5s, 2, node->ledger.stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::all, nano::stat::dir::out)); @@ -246,7 +246,7 @@ TEST (confirmation_callback, dependent_election) // Wait for blocks to be confirmed in ledger, callbacks will happen after ASSERT_TIMELY_EQ (5s, 3, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in)); // Once the item added to the confirming set no longer exists, callbacks have completed - ASSERT_TIMELY (5s, !node->confirmation_height_processor.exists (send2->hash ())); + ASSERT_TIMELY (5s, !node->confirming_set.exists (send2->hash ())); ASSERT_EQ (1, node->stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::active_quorum, nano::stat::dir::out)); ASSERT_EQ (1, node->stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::active_conf_height, nano::stat::dir::out)); diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index 988008f2..f9bc35ec 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -1984,7 +1984,7 @@ TEST (node, DISABLED_local_votes_cache_batch) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) .build (); ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send1)); - node.confirmation_height_processor.add (send1->hash ()); + node.confirming_set.add (send1->hash ()); ASSERT_TIMELY (5s, node.ledger.block_confirmed (node.store.tx_begin_read (), send1->hash ())); auto send2 = nano::state_block_builder () .account (nano::dev::genesis_key.pub) diff --git a/nano/core_test/request_aggregator.cpp b/nano/core_test/request_aggregator.cpp index ebaa7553..99d429ab 100644 --- a/nano/core_test/request_aggregator.cpp +++ b/nano/core_test/request_aggregator.cpp @@ -80,7 +80,7 @@ TEST (request_aggregator, one_update) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) .build (); ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send1)); - node.confirmation_height_processor.add (send1->hash ()); + node.confirming_set.add (send1->hash ()); ASSERT_TIMELY (5s, node.ledger.block_confirmed (node.store.tx_begin_read (), send1->hash ())); auto send2 = nano::state_block_builder () .account (nano::dev::genesis_key.pub) @@ -146,7 +146,7 @@ TEST (request_aggregator, two) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) .build (); ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send1)); - node.confirmation_height_processor.add (send1->hash ()); + node.confirming_set.add (send1->hash ()); ASSERT_TIMELY (5s, node.ledger.block_confirmed (node.store.tx_begin_read (), send1->hash ())); auto send2 = builder.make_block () .account (nano::dev::genesis_key.pub) diff --git a/nano/lib/locks.cpp b/nano/lib/locks.cpp index 231ef13c..f90f08b5 100644 --- a/nano/lib/locks.cpp +++ b/nano/lib/locks.cpp @@ -257,8 +257,6 @@ char const * nano::mutex_identifier (mutexes mutex) return "block_uniquer"; case mutexes::blockstore_cache: return "blockstore_cache"; - case mutexes::confirmation_height_processor: - return "confirmation_height_processor"; case mutexes::election_winner_details: return "election_winner_details"; case mutexes::gap_cache: @@ -286,4 +284,4 @@ char const * nano::mutex_identifier (mutexes mutex) } throw std::runtime_error ("Invalid mutexes enum specified"); -} \ No newline at end of file +} diff --git a/nano/lib/locks.hpp b/nano/lib/locks.hpp index 1bbe0a7f..0b5f7663 100644 --- a/nano/lib/locks.hpp +++ b/nano/lib/locks.hpp @@ -23,7 +23,6 @@ enum class mutexes block_processor, block_uniquer, blockstore_cache, - confirmation_height_processor, election_winner_details, gap_cache, network_filter, diff --git a/nano/nano_node/entry.cpp b/nano/nano_node/entry.cpp index 9b8486ed..55e6d7f5 100644 --- a/nano/nano_node/entry.cpp +++ b/nano/nano_node/entry.cpp @@ -1213,7 +1213,7 @@ int main (int argc, char * const * argv) // Confirm blocks for node1 for (auto & block : blocks) { - node1->confirmation_height_processor.add (block->hash ()); + node1->confirming_set.add (block->hash ()); } while (node1->ledger.cache.cemented_count != node1->ledger.cache.block_count) { diff --git a/nano/node/CMakeLists.txt b/nano/node/CMakeLists.txt index b21cdae1..7600ef9d 100644 --- a/nano/node/CMakeLists.txt +++ b/nano/node/CMakeLists.txt @@ -61,12 +61,6 @@ add_library( common.cpp confirming_set.hpp confirming_set.cpp - confirmation_height_bounded.hpp - confirmation_height_bounded.cpp - confirmation_height_processor.hpp - confirmation_height_processor.cpp - confirmation_height_unbounded.hpp - confirmation_height_unbounded.cpp confirmation_solicitor.hpp confirmation_solicitor.cpp daemonconfig.hpp diff --git a/nano/node/active_transactions.cpp b/nano/node/active_transactions.cpp index 4393f097..708078a5 100644 --- a/nano/node/active_transactions.cpp +++ b/nano/node/active_transactions.cpp @@ -15,9 +15,9 @@ using namespace std::chrono; -nano::active_transactions::active_transactions (nano::node & node_a, nano::confirming_set & confirmation_height_processor_a, nano::block_processor & block_processor_a) : +nano::active_transactions::active_transactions (nano::node & node_a, nano::confirming_set & confirming_set, nano::block_processor & block_processor_a) : node{ node_a }, - confirmation_height_processor{ confirmation_height_processor_a }, + confirming_set{ confirming_set }, block_processor{ block_processor_a }, recently_confirmed{ 65536 }, recently_cemented{ node.config.confirmation_history_size }, @@ -26,12 +26,12 @@ nano::active_transactions::active_transactions (nano::node & node_a, nano::confi count_by_behavior.fill (0); // Zero initialize array // Register a callback which will get called after a block is cemented - confirmation_height_processor.cemented_observers.add ([this] (std::shared_ptr const & callback_block_a) { + confirming_set.cemented_observers.add ([this] (std::shared_ptr const & callback_block_a) { this->block_cemented_callback (callback_block_a); }); // Register a callback which will get called if a block is already cemented - confirmation_height_processor.block_already_cemented_observers.add ([this] (nano::block_hash const & hash_a) { + confirming_set.block_already_cemented_observers.add ([this] (nano::block_hash const & hash_a) { this->block_already_cemented_callback (hash_a); }); @@ -96,7 +96,7 @@ void nano::active_transactions::block_cemented_callback (std::shared_ptrget_status (); votes = election->votes_with_weight (); } - if (confirmation_height_processor.exists (block->hash ())) + if (confirming_set.exists (block->hash ())) { status.type = nano::election_status_type::active_confirmed_quorum; } diff --git a/nano/node/active_transactions.hpp b/nano/node/active_transactions.hpp index 08885480..7fded5f6 100644 --- a/nano/node/active_transactions.hpp +++ b/nano/node/active_transactions.hpp @@ -209,7 +209,7 @@ private: private: // Dependencies nano::node & node; - nano::confirming_set & confirmation_height_processor; + nano::confirming_set & confirming_set; nano::block_processor & block_processor; public: diff --git a/nano/node/confirmation_height_bounded.cpp b/nano/node/confirmation_height_bounded.cpp deleted file mode 100644 index dfb7dea6..00000000 --- a/nano/node/confirmation_height_bounded.cpp +++ /dev/null @@ -1,580 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -nano::confirmation_height_bounded::confirmation_height_bounded (nano::ledger & ledger_a, nano::write_database_queue & write_database_queue_a, std::chrono::milliseconds batch_separate_pending_min_time_a, nano::logger & logger_a, std::atomic & stopped_a, uint64_t & batch_write_size_a, std::function> const &)> const & notify_observers_callback_a, std::function const & notify_block_already_cemented_observers_callback_a, std::function const & awaiting_processing_size_callback_a) : - ledger (ledger_a), - write_database_queue (write_database_queue_a), - batch_separate_pending_min_time (batch_separate_pending_min_time_a), - logger (logger_a), - stopped (stopped_a), - batch_write_size (batch_write_size_a), - notify_observers_callback (notify_observers_callback_a), - notify_block_already_cemented_observers_callback (notify_block_already_cemented_observers_callback_a), - awaiting_processing_size_callback (awaiting_processing_size_callback_a) -{ -} - -// The next block hash to iterate over, the priority is as follows: -// 1 - The next block in the account chain for the last processed receive (if there is any) -// 2 - The next receive block which is closest to genesis -// 3 - The last checkpoint hit. -// 4 - The hash that was passed in originally. Either all checkpoints were exhausted (this can happen when there are many accounts to genesis) -// or all other blocks have been processed. -nano::confirmation_height_bounded::top_and_next_hash nano::confirmation_height_bounded::get_next_block (boost::optional const & next_in_receive_chain_a, boost::circular_buffer_space_optimized const & checkpoints_a, boost::circular_buffer_space_optimized const & receive_source_pairs, boost::optional & receive_details_a, nano::block const & original_block) -{ - top_and_next_hash next; - if (next_in_receive_chain_a.is_initialized ()) - { - next = *next_in_receive_chain_a; - } - else if (!receive_source_pairs.empty ()) - { - auto next_receive_source_pair = receive_source_pairs.back (); - receive_details_a = next_receive_source_pair.receive_details; - next = { next_receive_source_pair.source_hash, receive_details_a->next, receive_details_a->height + 1 }; - } - else if (!checkpoints_a.empty ()) - { - next = { checkpoints_a.back (), boost::none, 0 }; - } - else - { - next = { original_block.hash (), boost::none, 0 }; - } - - return next; -} - -void nano::confirmation_height_bounded::process (std::shared_ptr original_block) -{ - if (pending_empty ()) - { - clear_process_vars (); - timer.restart (); - } - - boost::optional next_in_receive_chain; - boost::circular_buffer_space_optimized checkpoints{ max_items }; - boost::circular_buffer_space_optimized receive_source_pairs{ max_items }; - nano::block_hash current; - bool first_iter = true; - auto transaction (ledger.store.tx_begin_read ()); - do - { - boost::optional receive_details; - auto hash_to_process = get_next_block (next_in_receive_chain, checkpoints, receive_source_pairs, receive_details, *original_block); - current = hash_to_process.top; - - auto top_level_hash = current; - std::shared_ptr block; - if (first_iter) - { - debug_assert (current == original_block->hash ()); - block = original_block; - } - else - { - block = ledger.block (transaction, current); - } - - if (!block) - { - if (ledger.pruning && ledger.store.pruned.exists (transaction, current)) - { - if (!receive_source_pairs.empty ()) - { - receive_source_pairs.pop_back (); - } - continue; - } - else - { - logger.critical (nano::log::type::conf_processor_bounded, "Ledger mismatch trying to set confirmation height for block {} (bounded processor)", current.to_string ()); - - release_assert (block); - } - } - auto account = block->account (); - - // Checks if we have encountered this account before but not commited changes yet, if so then update the cached confirmation height - nano::confirmation_height_info confirmation_height_info; - auto account_it = accounts_confirmed_info.find (account); - if (account_it != accounts_confirmed_info.cend ()) - { - confirmation_height_info.height = account_it->second.confirmed_height; - confirmation_height_info.frontier = account_it->second.iterated_frontier; - } - else - { - ledger.store.confirmation_height.get (transaction, account, confirmation_height_info); - // This block was added to the confirmation height processor but is already confirmed - if (first_iter && confirmation_height_info.height >= block->sideband ().height && current == original_block->hash ()) - { - notify_block_already_cemented_observers_callback (original_block->hash ()); - } - } - - auto block_height = block->sideband ().height; - bool already_cemented = confirmation_height_info.height >= block_height; - - // If we are not already at the bottom of the account chain (1 above cemented frontier) then find it - if (!already_cemented && block_height - confirmation_height_info.height > 1) - { - if (block_height - confirmation_height_info.height == 2) - { - // If there is 1 uncemented block in-between this block and the cemented frontier, - // we can just use the previous block to get the least unconfirmed hash. - current = block->previous (); - --block_height; - } - else if (!next_in_receive_chain.is_initialized ()) - { - current = get_least_unconfirmed_hash_from_top_level (transaction, current, account, confirmation_height_info, block_height); - } - else - { - // Use the cached successor of the last receive which saves having to do more IO in get_least_unconfirmed_hash_from_top_level - // as we already know what the next block we should process should be. - current = *hash_to_process.next; - block_height = hash_to_process.next_height; - } - } - - auto top_most_non_receive_block_hash = current; - - bool hit_receive = false; - if (!already_cemented) - { - hit_receive = iterate (transaction, block_height, current, checkpoints, top_most_non_receive_block_hash, top_level_hash, receive_source_pairs, account); - } - - // Exit early when the processor has been stopped, otherwise this function may take a - // while (and hence keep the process running) if updating a long chain. - if (stopped) - { - break; - } - - // next_in_receive_chain can be modified when writing, so need to cache it here before resetting - auto is_set = next_in_receive_chain.is_initialized (); - next_in_receive_chain = boost::none; - - // Need to also handle the case where we are hitting receives where the sends below should be confirmed - if (!hit_receive || (receive_source_pairs.size () == 1 && top_most_non_receive_block_hash != current)) - { - preparation_data preparation_data{ transaction, top_most_non_receive_block_hash, already_cemented, checkpoints, account_it, confirmation_height_info, account, block_height, current, receive_details, next_in_receive_chain }; - prepare_iterated_blocks_for_cementing (preparation_data); - - // If used the top level, don't pop off the receive source pair because it wasn't used - if (!is_set && !receive_source_pairs.empty ()) - { - receive_source_pairs.pop_back (); - } - - auto total_pending_write_block_count = std::accumulate (pending_writes.cbegin (), pending_writes.cend (), uint64_t (0), [] (uint64_t total, auto const & write_details_a) { - return total += write_details_a.top_height - write_details_a.bottom_height + 1; - }); - - auto max_batch_write_size_reached = (total_pending_write_block_count >= batch_write_size); - // When there are a lot of pending confirmation height blocks, it is more efficient to - // bulk some of them up to enable better write performance which becomes the bottleneck. - auto min_time_exceeded = (timer.since_start () >= batch_separate_pending_min_time); - auto finished_iterating = current == original_block->hash (); - auto non_awaiting_processing = awaiting_processing_size_callback () == 0; - auto should_output = finished_iterating && (non_awaiting_processing || min_time_exceeded); - auto force_write = pending_writes.size () >= pending_writes_max_size || accounts_confirmed_info.size () >= pending_writes_max_size; - - if ((max_batch_write_size_reached || should_output || force_write) && !pending_writes.empty ()) - { - // If nothing is currently using the database write lock then write the cemented pending blocks otherwise continue iterating - if (write_database_queue.process (nano::writer::confirmation_height)) - { - auto scoped_write_guard = write_database_queue.pop (); - cement_blocks (scoped_write_guard); - } - else if (force_write) - { - auto scoped_write_guard = write_database_queue.wait (nano::writer::confirmation_height); - cement_blocks (scoped_write_guard); - } - } - } - - first_iter = false; - transaction.refresh (); - } while ((!receive_source_pairs.empty () || current != original_block->hash ()) && !stopped); - - debug_assert (checkpoints.empty ()); -} - -nano::block_hash nano::confirmation_height_bounded::get_least_unconfirmed_hash_from_top_level (store::transaction const & transaction_a, nano::block_hash const & hash_a, nano::account const & account_a, nano::confirmation_height_info const & confirmation_height_info_a, uint64_t & block_height_a) -{ - nano::block_hash least_unconfirmed_hash = hash_a; - if (confirmation_height_info_a.height != 0) - { - if (block_height_a > confirmation_height_info_a.height) - { - auto block = ledger.block (transaction_a, confirmation_height_info_a.frontier); - release_assert (block != nullptr); - least_unconfirmed_hash = block->sideband ().successor; - block_height_a = block->sideband ().height + 1; - } - } - else - { - // No blocks have been confirmed, so the first block will be the open block - auto info = ledger.account_info (transaction_a, account_a); - release_assert (info); - least_unconfirmed_hash = info->open_block; - block_height_a = 1; - } - return least_unconfirmed_hash; -} - -bool nano::confirmation_height_bounded::iterate (store::read_transaction const & transaction_a, uint64_t bottom_height_a, nano::block_hash const & bottom_hash_a, boost::circular_buffer_space_optimized & checkpoints_a, nano::block_hash & top_most_non_receive_block_hash_a, nano::block_hash const & top_level_hash_a, boost::circular_buffer_space_optimized & receive_source_pairs_a, nano::account const & account_a) -{ - bool reached_target = false; - bool hit_receive = false; - auto hash = bottom_hash_a; - uint64_t num_blocks = 0; - while (!hash.is_zero () && !reached_target && !stopped) - { - // Keep iterating upwards until we either reach the desired block or the second receive. - // Once a receive is cemented, we can cement all blocks above it until the next receive, so store those details for later. - ++num_blocks; - auto block = ledger.block (transaction_a, hash); - if (block->is_receive () && ledger.block_exists (transaction_a, block->source ())) - { - hit_receive = true; - reached_target = true; - auto const & sideband (block->sideband ()); - auto next = !sideband.successor.is_zero () && sideband.successor != top_level_hash_a ? boost::optional (sideband.successor) : boost::none; - receive_source_pairs_a.push_back ({ receive_chain_details{ account_a, sideband.height, hash, top_level_hash_a, next, bottom_height_a, bottom_hash_a }, block->source () }); - // Store a checkpoint every max_items so that we can always traverse a long number of accounts to genesis - if (receive_source_pairs_a.size () % max_items == 0) - { - checkpoints_a.push_back (top_level_hash_a); - } - } - else - { - // Found a send/change/epoch block which isn't the desired top level - top_most_non_receive_block_hash_a = hash; - if (hash == top_level_hash_a) - { - reached_target = true; - } - else - { - hash = block->sideband ().successor; - } - } - - // We could be traversing a very large account so we don't want to open read transactions for too long. - if ((num_blocks > 0) && num_blocks % batch_read_size == 0) - { - transaction_a.refresh (); - } - } - - return hit_receive; -} - -// Once the path to genesis has been iterated to, we can begin to cement the lowest blocks in the accounts. This sets up -// the non-receive blocks which have been iterated for an account, and the associated receive block. -void nano::confirmation_height_bounded::prepare_iterated_blocks_for_cementing (preparation_data & preparation_data_a) -{ - if (!preparation_data_a.already_cemented) - { - // Add the non-receive blocks iterated for this account - auto block_height = (ledger.height (preparation_data_a.transaction, preparation_data_a.top_most_non_receive_block_hash)); - if (block_height > preparation_data_a.confirmation_height_info.height) - { - confirmed_info confirmed_info_l{ block_height, preparation_data_a.top_most_non_receive_block_hash }; - if (preparation_data_a.account_it != accounts_confirmed_info.cend ()) - { - preparation_data_a.account_it->second = confirmed_info_l; - } - else - { - accounts_confirmed_info.emplace (preparation_data_a.account, confirmed_info_l); - ++accounts_confirmed_info_size; - } - - preparation_data_a.checkpoints.erase (std::remove (preparation_data_a.checkpoints.begin (), preparation_data_a.checkpoints.end (), preparation_data_a.top_most_non_receive_block_hash), preparation_data_a.checkpoints.end ()); - pending_writes.emplace_back (preparation_data_a.account, preparation_data_a.bottom_height, preparation_data_a.bottom_most, block_height, preparation_data_a.top_most_non_receive_block_hash); - ++pending_writes_size; - } - } - - // Add the receive block and all non-receive blocks above that one - auto & receive_details = preparation_data_a.receive_details; - if (receive_details) - { - auto receive_confirmed_info_it = accounts_confirmed_info.find (receive_details->account); - if (receive_confirmed_info_it != accounts_confirmed_info.cend ()) - { - auto & receive_confirmed_info = receive_confirmed_info_it->second; - receive_confirmed_info.confirmed_height = receive_details->height; - receive_confirmed_info.iterated_frontier = receive_details->hash; - } - else - { - accounts_confirmed_info.emplace (std::piecewise_construct, std::forward_as_tuple (receive_details->account), std::forward_as_tuple (receive_details->height, receive_details->hash)); - ++accounts_confirmed_info_size; - } - - if (receive_details->next.is_initialized ()) - { - preparation_data_a.next_in_receive_chain = top_and_next_hash{ receive_details->top_level, receive_details->next, receive_details->height + 1 }; - } - else - { - preparation_data_a.checkpoints.erase (std::remove (preparation_data_a.checkpoints.begin (), preparation_data_a.checkpoints.end (), receive_details->hash), preparation_data_a.checkpoints.end ()); - } - - pending_writes.emplace_back (receive_details->account, receive_details->bottom_height, receive_details->bottom_most, receive_details->height, receive_details->hash); - ++pending_writes_size; - } -} - -void nano::confirmation_height_bounded::cement_blocks (nano::write_guard & scoped_write_guard_a) -{ - // Will contain all blocks that have been cemented (bounded by batch_write_size) - // and will get run through the cemented observer callback - std::vector> cemented_blocks; - auto const maximum_batch_write_time = 250; // milliseconds - auto const maximum_batch_write_time_increase_cutoff = maximum_batch_write_time - (maximum_batch_write_time / 5); - auto const amount_to_change = batch_write_size / 10; // 10% - auto const minimum_batch_write_size = 16384u; - nano::timer<> cemented_batch_timer; - auto error = false; - { - // This only writes to the confirmation_height table and is the only place to do so in a single process - auto transaction (ledger.store.tx_begin_write ({}, { nano::tables::confirmation_height })); - cemented_batch_timer.start (); - // Cement all pending entries, each entry is specific to an account and contains the least amount - // of blocks to retain consistent cementing across all account chains to genesis. - while (!error && !pending_writes.empty ()) - { - auto const & pending = pending_writes.front (); - auto const & account = pending.account; - - auto write_confirmation_height = [&account, &ledger = ledger, &transaction] (uint64_t num_blocks_cemented, uint64_t confirmation_height, nano::block_hash const & confirmed_frontier) { -#ifndef NDEBUG - // Extra debug checks - nano::confirmation_height_info confirmation_height_info; - ledger.store.confirmation_height.get (transaction, account, confirmation_height_info); - auto block = ledger.block (transaction, confirmed_frontier); - debug_assert (block != nullptr); - debug_assert (block->sideband ().height == confirmation_height_info.height + num_blocks_cemented); -#endif - ledger.store.confirmation_height.put (transaction, account, nano::confirmation_height_info{ confirmation_height, confirmed_frontier }); - ledger.cache.cemented_count += num_blocks_cemented; - ledger.stats.add (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in, num_blocks_cemented); - ledger.stats.add (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed_bounded, nano::stat::dir::in, num_blocks_cemented); - }; - - nano::confirmation_height_info confirmation_height_info; - ledger.store.confirmation_height.get (transaction, pending.account, confirmation_height_info); - - // Some blocks need to be cemented at least - if (pending.top_height > confirmation_height_info.height) - { - // The highest hash which will be cemented - nano::block_hash new_cemented_frontier; - uint64_t num_blocks_confirmed = 0; - uint64_t start_height = 0; - if (pending.bottom_height > confirmation_height_info.height) - { - new_cemented_frontier = pending.bottom_hash; - // If we are higher than the cemented frontier, we should be exactly 1 block above - debug_assert (pending.bottom_height == confirmation_height_info.height + 1); - num_blocks_confirmed = pending.top_height - pending.bottom_height + 1; - start_height = pending.bottom_height; - } - else - { - auto block = ledger.block (transaction, confirmation_height_info.frontier); - new_cemented_frontier = block->sideband ().successor; - num_blocks_confirmed = pending.top_height - confirmation_height_info.height; - start_height = confirmation_height_info.height + 1; - } - - auto total_blocks_cemented = 0; - auto block = ledger.block (transaction, new_cemented_frontier); - - // Cementing starts from the bottom of the chain and works upwards. This is because chains can have effectively - // an infinite number of send/change blocks in a row. We don't want to hold the write transaction open for too long. - for (auto num_blocks_iterated = 0; num_blocks_confirmed - num_blocks_iterated != 0; ++num_blocks_iterated) - { - if (!block) - { - logger.critical (nano::log::type::conf_processor_bounded, "Failed to write confirmation height for block {} (bounded processor)", new_cemented_frontier.to_string ()); - - // Undo any blocks about to be cemented from this account for this pending write. - cemented_blocks.erase (cemented_blocks.end () - num_blocks_iterated, cemented_blocks.end ()); - error = true; - break; - } - - auto last_iteration = (num_blocks_confirmed - num_blocks_iterated) == 1; - - cemented_blocks.emplace_back (block); - - // Flush these callbacks and continue as we write in batches (ideally maximum 250ms) to not hold write db transaction for too long. - // Include a tolerance to save having to potentially wait on the block processor if the number of blocks to cement is only a bit higher than the max. - if (cemented_blocks.size () > batch_write_size + (batch_write_size / 10)) - { - auto time_spent_cementing = cemented_batch_timer.since_start ().count (); - auto num_blocks_cemented = num_blocks_iterated - total_blocks_cemented + 1; - total_blocks_cemented += num_blocks_cemented; - write_confirmation_height (num_blocks_cemented, start_height + total_blocks_cemented - 1, new_cemented_frontier); - transaction.commit (); - - // Update the maximum amount of blocks to write next time based on the time it took to cement this batch. - if (time_spent_cementing > maximum_batch_write_time) - { - // Reduce (unless we have hit a floor) - batch_write_size = std::max (minimum_batch_write_size, batch_write_size - amount_to_change); - } - else if (time_spent_cementing < maximum_batch_write_time_increase_cutoff) - { - // Increase amount of blocks written for next batch if the time for writing this one is sufficiently lower than the max time to warrant changing - batch_write_size += amount_to_change; - } - - scoped_write_guard_a.release (); - notify_observers_callback (cemented_blocks); - cemented_blocks.clear (); - - // Only aquire transaction if there are blocks left - if (!(last_iteration && pending_writes.size () == 1)) - { - scoped_write_guard_a = write_database_queue.wait (nano::writer::confirmation_height); - transaction.renew (); - } - cemented_batch_timer.restart (); - } - - // Get the next block in the chain until we have reached the final desired one - if (!last_iteration) - { - new_cemented_frontier = block->sideband ().successor; - block = ledger.block (transaction, new_cemented_frontier); - } - else - { - // Confirm it is indeed the last one - debug_assert (new_cemented_frontier == pending.top_hash); - } - } - - if (error) - { - // There was an error writing a block, do not process any more - break; - } - - auto num_blocks_cemented = num_blocks_confirmed - total_blocks_cemented; - if (num_blocks_cemented > 0) - { - write_confirmation_height (num_blocks_cemented, pending.top_height, new_cemented_frontier); - } - } - - auto it = accounts_confirmed_info.find (pending.account); - if (it != accounts_confirmed_info.cend () && it->second.confirmed_height == pending.top_height) - { - accounts_confirmed_info.erase (pending.account); - --accounts_confirmed_info_size; - } - pending_writes.pop_front (); - --pending_writes_size; - } - } - - auto time_spent_cementing = cemented_batch_timer.since_start (); - - // Scope guard could have been released earlier (0 cemented_blocks would indicate that) - if (scoped_write_guard_a.is_owned () && !cemented_blocks.empty ()) - { - scoped_write_guard_a.release (); - notify_observers_callback (cemented_blocks); - } - - // Bail if there was an error. This indicates that there was a fatal issue with the ledger - // (the blocks probably got rolled back when they shouldn't have). - release_assert (!error); - - if (time_spent_cementing.count () > maximum_batch_write_time) - { - // Reduce (unless we have hit a floor) - batch_write_size = std::max (minimum_batch_write_size, batch_write_size - amount_to_change); - } - - debug_assert (pending_writes.empty ()); - debug_assert (pending_writes_size == 0); - timer.restart (); -} - -bool nano::confirmation_height_bounded::pending_empty () const -{ - return pending_writes.empty (); -} - -void nano::confirmation_height_bounded::clear_process_vars () -{ - accounts_confirmed_info.clear (); - accounts_confirmed_info_size = 0; -} - -nano::confirmation_height_bounded::receive_chain_details::receive_chain_details (nano::account const & account_a, uint64_t height_a, nano::block_hash const & hash_a, nano::block_hash const & top_level_a, boost::optional next_a, uint64_t bottom_height_a, nano::block_hash const & bottom_most_a) : - account (account_a), - height (height_a), - hash (hash_a), - top_level (top_level_a), - next (next_a), - bottom_height (bottom_height_a), - bottom_most (bottom_most_a) -{ -} - -nano::confirmation_height_bounded::write_details::write_details (nano::account const & account_a, uint64_t bottom_height_a, nano::block_hash const & bottom_hash_a, uint64_t top_height_a, nano::block_hash const & top_hash_a) : - account (account_a), - bottom_height (bottom_height_a), - bottom_hash (bottom_hash_a), - top_height (top_height_a), - top_hash (top_hash_a) -{ -} - -nano::confirmation_height_bounded::receive_source_pair::receive_source_pair (confirmation_height_bounded::receive_chain_details const & receive_details_a, const block_hash & source_a) : - receive_details (receive_details_a), - source_hash (source_a) -{ -} - -nano::confirmation_height_bounded::confirmed_info::confirmed_info (uint64_t confirmed_height_a, nano::block_hash const & iterated_frontier_a) : - confirmed_height (confirmed_height_a), - iterated_frontier (iterated_frontier_a) -{ -} - -std::unique_ptr nano::collect_container_info (confirmation_height_bounded & confirmation_height_bounded, std::string const & name_a) -{ - auto composite = std::make_unique (name_a); - composite->add_component (std::make_unique (container_info{ "pending_writes", confirmation_height_bounded.pending_writes_size, sizeof (decltype (confirmation_height_bounded.pending_writes)::value_type) })); - composite->add_component (std::make_unique (container_info{ "accounts_confirmed_info", confirmation_height_bounded.accounts_confirmed_info_size, sizeof (decltype (confirmation_height_bounded.accounts_confirmed_info)::value_type) })); - return composite; -} diff --git a/nano/node/confirmation_height_bounded.hpp b/nano/node/confirmation_height_bounded.hpp deleted file mode 100644 index a5052b14..00000000 --- a/nano/node/confirmation_height_bounded.hpp +++ /dev/null @@ -1,135 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include - -namespace nano -{ -class ledger; -class write_database_queue; -class write_guard; - -class confirmation_height_bounded final -{ -public: - confirmation_height_bounded (nano::ledger &, nano::write_database_queue &, std::chrono::milliseconds batch_separate_pending_min_time, nano::logger &, std::atomic & stopped, uint64_t & batch_write_size, std::function> const &)> const & cemented_callback, std::function const & already_cemented_callback, std::function const & awaiting_processing_size_query); - - bool pending_empty () const; - void clear_process_vars (); - void process (std::shared_ptr original_block); - void cement_blocks (nano::write_guard & scoped_write_guard_a); - -private: - class top_and_next_hash final - { - public: - nano::block_hash top; - boost::optional next; - uint64_t next_height; - }; - - class confirmed_info - { - public: - confirmed_info (uint64_t confirmed_height_a, nano::block_hash const & iterated_frontier); - uint64_t confirmed_height; - nano::block_hash iterated_frontier; - }; - - class write_details final - { - public: - write_details (nano::account const &, uint64_t, nano::block_hash const &, uint64_t, nano::block_hash const &); - nano::account account; - // This is the first block hash (bottom most) which is not cemented - uint64_t bottom_height; - nano::block_hash bottom_hash; - // Desired cemented frontier - uint64_t top_height; - nano::block_hash top_hash; - }; - - /** The maximum number of blocks to be read in while iterating over a long account chain */ - uint64_t const batch_read_size = 65536; - - /** The maximum number of various containers to keep the memory bounded */ - uint32_t const max_items{ 131072 }; - - // All of the atomic variables here just track the size for use in collect_container_info. - // This is so that no mutexes are needed during the algorithm itself, which would otherwise be needed - // for the sake of a rarely used RPC call for debugging purposes. As such the sizes are not being acted - // upon in any way (does not synchronize with any other data). - // This allows the load and stores to use relaxed atomic memory ordering. - std::deque pending_writes; - nano::relaxed_atomic_integral pending_writes_size{ 0 }; - uint32_t const pending_writes_max_size{ max_items }; - /* Holds confirmation height/cemented frontier in memory for accounts while iterating */ - std::unordered_map accounts_confirmed_info; - nano::relaxed_atomic_integral accounts_confirmed_info_size{ 0 }; - - class receive_chain_details final - { - public: - receive_chain_details (nano::account const &, uint64_t, nano::block_hash const &, nano::block_hash const &, boost::optional, uint64_t, nano::block_hash const &); - nano::account account; - uint64_t height; - nano::block_hash hash; - nano::block_hash top_level; - boost::optional next; - uint64_t bottom_height; - nano::block_hash bottom_most; - }; - - class preparation_data final - { - public: - store::transaction const & transaction; - nano::block_hash const & top_most_non_receive_block_hash; - bool already_cemented; - boost::circular_buffer_space_optimized & checkpoints; - decltype (accounts_confirmed_info.begin ()) account_it; - nano::confirmation_height_info const & confirmation_height_info; - nano::account const & account; - uint64_t bottom_height; - nano::block_hash const & bottom_most; - boost::optional & receive_details; - boost::optional & next_in_receive_chain; - }; - - class receive_source_pair final - { - public: - receive_source_pair (receive_chain_details const &, nano::block_hash const &); - - receive_chain_details receive_details; - nano::block_hash source_hash; - }; - - nano::timer timer; - - top_and_next_hash get_next_block (boost::optional const &, boost::circular_buffer_space_optimized const &, boost::circular_buffer_space_optimized const & receive_source_pairs, boost::optional &, nano::block const & original_block); - nano::block_hash get_least_unconfirmed_hash_from_top_level (store::transaction const &, nano::block_hash const &, nano::account const &, nano::confirmation_height_info const &, uint64_t &); - void prepare_iterated_blocks_for_cementing (preparation_data &); - bool iterate (store::read_transaction const &, uint64_t, nano::block_hash const &, boost::circular_buffer_space_optimized &, nano::block_hash &, nano::block_hash const &, boost::circular_buffer_space_optimized &, nano::account const &); - - nano::ledger & ledger; - nano::write_database_queue & write_database_queue; - std::chrono::milliseconds batch_separate_pending_min_time; - nano::logger & logger; - std::atomic & stopped; - uint64_t & batch_write_size; - std::function> const &)> notify_observers_callback; - std::function notify_block_already_cemented_observers_callback; - std::function awaiting_processing_size_callback; - - friend std::unique_ptr collect_container_info (confirmation_height_bounded &, std::string const & name_a); -}; - -std::unique_ptr collect_container_info (confirmation_height_bounded &, std::string const & name_a); -} diff --git a/nano/node/confirmation_height_processor.cpp b/nano/node/confirmation_height_processor.cpp deleted file mode 100644 index 5161980e..00000000 --- a/nano/node/confirmation_height_processor.cpp +++ /dev/null @@ -1,225 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -nano::confirmation_height_processor::confirmation_height_processor (nano::ledger & ledger_a, nano::write_database_queue & write_database_queue_a, std::chrono::milliseconds batch_separate_pending_min_time_a, nano::logger & logger_a, boost::latch & latch, confirmation_height_mode mode_a) : - ledger (ledger_a), - write_database_queue (write_database_queue_a), - unbounded_processor ( - ledger_a, write_database_queue_a, batch_separate_pending_min_time_a, logger_a, stopped, batch_write_size, - /* cemented_callback */ [this] (auto & cemented_blocks) { this->notify_cemented (cemented_blocks); }, - /* already cemented_callback */ [this] (auto const & block_hash_a) { this->notify_already_cemented (block_hash_a); }, - /* awaiting_processing_size_query */ [this] () { return this->awaiting_processing_size (); }), - bounded_processor ( - ledger_a, write_database_queue_a, batch_separate_pending_min_time_a, logger_a, stopped, batch_write_size, - /* cemented_callback */ [this] (auto & cemented_blocks) { this->notify_cemented (cemented_blocks); }, - /* already cemented_callback */ [this] (auto const & block_hash_a) { this->notify_already_cemented (block_hash_a); }, - /* awaiting_processing_size_query */ [this] () { return this->awaiting_processing_size (); }), - thread ([this, &latch, mode_a] () { - nano::thread_role::set (nano::thread_role::name::confirmation_height_processing); - // Do not start running the processing thread until other threads have finished their operations - latch.wait (); - this->run (mode_a); - }) -{ -} - -nano::confirmation_height_processor::~confirmation_height_processor () -{ - stop (); -} - -void nano::confirmation_height_processor::stop () -{ - { - nano::lock_guard guard (mutex); - stopped = true; - } - condition.notify_one (); - if (thread.joinable ()) - { - thread.join (); - } -} - -void nano::confirmation_height_processor::run (confirmation_height_mode mode_a) -{ - nano::unique_lock lk (mutex); - while (!stopped) - { - if (!paused && !awaiting_processing.empty ()) - { - lk.unlock (); - if (bounded_processor.pending_empty () && unbounded_processor.pending_empty ()) - { - lk.lock (); - original_hashes_pending.clear (); - lk.unlock (); - } - - set_next_hash (); - - auto const num_blocks_to_use_unbounded = confirmation_height::unbounded_cutoff; - auto blocks_within_automatic_unbounded_selection = (ledger.cache.block_count < num_blocks_to_use_unbounded || ledger.cache.block_count - num_blocks_to_use_unbounded < ledger.cache.cemented_count); - - // Don't want to mix up pending writes across different processors - auto valid_unbounded = (mode_a == confirmation_height_mode::automatic && blocks_within_automatic_unbounded_selection && bounded_processor.pending_empty ()); - auto force_unbounded = (!unbounded_processor.pending_empty () || mode_a == confirmation_height_mode::unbounded); - if (force_unbounded || valid_unbounded) - { - debug_assert (bounded_processor.pending_empty ()); - unbounded_processor.process (original_block); - } - else - { - debug_assert (mode_a == confirmation_height_mode::bounded || mode_a == confirmation_height_mode::automatic); - debug_assert (unbounded_processor.pending_empty ()); - bounded_processor.process (original_block); - } - - lk.lock (); - } - else - { - auto lock_and_cleanup = [&lk, this] () { - lk.lock (); - original_block = nullptr; - original_hashes_pending.clear (); - bounded_processor.clear_process_vars (); - unbounded_processor.clear_process_vars (); - }; - - if (!paused) - { - lk.unlock (); - - // If there are blocks pending cementing, then make sure we flush out the remaining writes - if (!bounded_processor.pending_empty ()) - { - debug_assert (unbounded_processor.pending_empty ()); - { - auto scoped_write_guard = write_database_queue.wait (nano::writer::confirmation_height); - bounded_processor.cement_blocks (scoped_write_guard); - } - lock_and_cleanup (); - } - else if (!unbounded_processor.pending_empty ()) - { - debug_assert (bounded_processor.pending_empty ()); - { - auto scoped_write_guard = write_database_queue.wait (nano::writer::confirmation_height); - unbounded_processor.cement_blocks (scoped_write_guard); - } - lock_and_cleanup (); - } - else - { - lock_and_cleanup (); - // A block could have been confirmed during the re-locking - if (awaiting_processing.empty ()) - { - condition.wait (lk); - } - } - } - else - { - // Pausing is only utilised in some tests to help prevent it processing added blocks until required. - original_block = nullptr; - condition.wait (lk); - } - } - } -} - -// Pausing only affects processing new blocks, not the current one being processed. Currently only used in tests -void nano::confirmation_height_processor::pause () -{ - nano::lock_guard lk (mutex); - paused = true; -} - -void nano::confirmation_height_processor::unpause () -{ - { - nano::lock_guard lk (mutex); - paused = false; - } - condition.notify_one (); -} - -void nano::confirmation_height_processor::add (std::shared_ptr const & block_a) -{ - { - nano::lock_guard lk (mutex); - awaiting_processing.get ().emplace_back (block_a); - } - condition.notify_one (); -} - -void nano::confirmation_height_processor::set_next_hash () -{ - nano::lock_guard guard (mutex); - debug_assert (!awaiting_processing.empty ()); - original_block = awaiting_processing.get ().front ().block; - original_hashes_pending.insert (original_block->hash ()); - awaiting_processing.get ().pop_front (); -} - -void nano::confirmation_height_processor::notify_cemented (std::vector> const & cemented_blocks) -{ - for (auto const & block_callback_data : cemented_blocks) - { - cemented_observers.notify (block_callback_data); - } -} - -void nano::confirmation_height_processor::notify_already_cemented (nano::block_hash const & hash_already_cemented_a) -{ - block_already_cemented_observers.notify (hash_already_cemented_a); -} - -std::unique_ptr nano::collect_container_info (confirmation_height_processor & confirmation_height_processor_a, std::string const & name_a) -{ - auto composite = std::make_unique (name_a); - - composite->add_component (std::make_unique (container_info{ "awaiting_processing", confirmation_height_processor_a.awaiting_processing_size (), sizeof (decltype (confirmation_height_processor_a.awaiting_processing)::value_type) })); - composite->add_component (collect_container_info (confirmation_height_processor_a.bounded_processor, "bounded_processor")); - composite->add_component (collect_container_info (confirmation_height_processor_a.unbounded_processor, "unbounded_processor")); - return composite; -} - -std::size_t nano::confirmation_height_processor::awaiting_processing_size () const -{ - nano::lock_guard guard (mutex); - return awaiting_processing.size (); -} - -bool nano::confirmation_height_processor::is_processing_added_block (nano::block_hash const & hash_a) const -{ - nano::lock_guard guard (mutex); - return original_hashes_pending.count (hash_a) > 0 || awaiting_processing.get ().count (hash_a) > 0; -} - -bool nano::confirmation_height_processor::exists (nano::block_hash const & hash_a) const -{ - return is_processing_added_block (hash_a) || unbounded_processor.has_iterated_over_block (hash_a); -} - -nano::block_hash nano::confirmation_height_processor::current () const -{ - nano::lock_guard lk (mutex); - return original_block ? original_block->hash () : 0; -} - -std::reference_wrapper nano::confirmation_height_processor::block_wrapper::hash () const -{ - return block->hash (); -} diff --git a/nano/node/confirmation_height_processor.hpp b/nano/node/confirmation_height_processor.hpp deleted file mode 100644 index 2ab69fd6..00000000 --- a/nano/node/confirmation_height_processor.hpp +++ /dev/null @@ -1,113 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -namespace mi = boost::multi_index; -namespace boost -{ -class latch; -} -namespace nano -{ -class ledger; -class write_database_queue; - -class confirmation_height_processor final -{ -public: - confirmation_height_processor (nano::ledger &, nano::write_database_queue &, std::chrono::milliseconds, nano::logger &, boost::latch & initialized_latch, confirmation_height_mode = confirmation_height_mode::automatic); - ~confirmation_height_processor (); - - void pause (); - void unpause (); - void stop (); - void add (std::shared_ptr const &); - void run (confirmation_height_mode); - std::size_t awaiting_processing_size () const; - bool is_processing_added_block (nano::block_hash const & hash_a) const; - bool exists (nano::block_hash const &) const; - nano::block_hash current () const; - - nano::observer_set const &> cemented_observers; - nano::observer_set block_already_cemented_observers; - -private: - mutable nano::mutex mutex{ mutex_identifier (mutexes::confirmation_height_processor) }; - - // Hashes which have been added to the confirmation height processor, but not yet processed - struct block_wrapper - { - explicit block_wrapper (std::shared_ptr const & block_a) : - block (block_a) - { - } - - std::reference_wrapper hash () const; - - std::shared_ptr block; - }; - // clang-format off - class tag_sequence {}; - class tag_hash {}; - boost::multi_index_container>, - mi::hashed_unique, - mi::const_mem_fun, &block_wrapper::hash>>>> awaiting_processing; - // clang-format on - - // Hashes which have been added and processed, but have not been cemented - std::unordered_set original_hashes_pending; - bool paused{ false }; - - /** This is the last block popped off the confirmation height pending collection */ - std::shared_ptr original_block; - - nano::condition_variable condition; - std::atomic stopped{ false }; - - nano::ledger & ledger; - nano::write_database_queue & write_database_queue; - /** The maximum amount of blocks to write at once. This is dynamically modified by the bounded processor based on previous write performance **/ - uint64_t batch_write_size{ 16384 }; - - confirmation_height_unbounded unbounded_processor; - confirmation_height_bounded bounded_processor; - std::thread thread; - - void set_next_hash (); - void notify_cemented (std::vector> const &); - void notify_already_cemented (nano::block_hash const &); - - friend std::unique_ptr collect_container_info (confirmation_height_processor &, std::string const &); - -private: // Tests - friend class confirmation_height_pending_observer_callbacks_Test; - friend class confirmation_height_dependent_election_Test; - friend class confirmation_height_dependent_election_after_already_cemented_Test; - friend class confirmation_height_dynamic_algorithm_no_transition_while_pending_Test; - friend class confirmation_height_many_accounts_many_confirmations_Test; - friend class confirmation_height_long_chains_Test; - friend class confirmation_height_many_accounts_single_confirmation_Test; - friend class request_aggregator_cannot_vote_Test; - friend class active_transactions_pessimistic_elections_Test; -}; - -std::unique_ptr collect_container_info (confirmation_height_processor &, std::string const &); -} diff --git a/nano/node/confirmation_height_unbounded.cpp b/nano/node/confirmation_height_unbounded.cpp deleted file mode 100644 index 20e7101c..00000000 --- a/nano/node/confirmation_height_unbounded.cpp +++ /dev/null @@ -1,498 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -nano::confirmation_height_unbounded::confirmation_height_unbounded (nano::ledger & ledger_a, nano::write_database_queue & write_database_queue_a, std::chrono::milliseconds batch_separate_pending_min_time_a, nano::logger & logger_a, std::atomic & stopped_a, uint64_t & batch_write_size_a, std::function> const &)> const & notify_observers_callback_a, std::function const & notify_block_already_cemented_observers_callback_a, std::function const & awaiting_processing_size_callback_a) : - ledger (ledger_a), - write_database_queue (write_database_queue_a), - batch_separate_pending_min_time (batch_separate_pending_min_time_a), - logger (logger_a), - stopped (stopped_a), - batch_write_size (batch_write_size_a), - notify_observers_callback (notify_observers_callback_a), - notify_block_already_cemented_observers_callback (notify_block_already_cemented_observers_callback_a), - awaiting_processing_size_callback (awaiting_processing_size_callback_a) -{ -} - -void nano::confirmation_height_unbounded::process (std::shared_ptr original_block) -{ - if (pending_empty ()) - { - clear_process_vars (); - timer.restart (); - } - std::shared_ptr receive_details; - auto current = original_block->hash (); - std::vector orig_block_callback_data; - - std::vector receive_source_pairs; - release_assert (receive_source_pairs.empty ()); - - bool first_iter = true; - auto read_transaction (ledger.store.tx_begin_read ()); - - do - { - if (!receive_source_pairs.empty ()) - { - receive_details = receive_source_pairs.back ().receive_details; - current = receive_source_pairs.back ().source_hash; - } - else - { - // If receive_details is set then this is the final iteration and we are back to the original chain. - // We need to confirm any blocks below the original hash (incl self) and the first receive block - // (if the original block is not already a receive) - if (receive_details) - { - current = original_block->hash (); - receive_details = nullptr; - } - } - - std::shared_ptr block; - if (first_iter) - { - debug_assert (current == original_block->hash ()); - // This is the original block passed so can use it directly - block = original_block; - nano::lock_guard guard (block_cache_mutex); - block_cache[original_block->hash ()] = original_block; - } - else - { - block = get_block_and_sideband (current, read_transaction); - } - if (!block) - { - logger.critical (nano::log::type::conf_processor_unbounded, "Ledger mismatch trying to set confirmation height for block {} (unbounded processor)", current.to_string ()); - } - release_assert (block); - - auto account = block->account (); - - auto block_height = block->sideband ().height; - uint64_t confirmation_height = 0; - auto account_it = confirmed_iterated_pairs.find (account); - if (account_it != confirmed_iterated_pairs.cend ()) - { - confirmation_height = account_it->second.confirmed_height; - } - else - { - nano::confirmation_height_info confirmation_height_info; - ledger.store.confirmation_height.get (read_transaction, account, confirmation_height_info); - confirmation_height = confirmation_height_info.height; - - // This block was added to the confirmation height processor but is already confirmed - if (first_iter && confirmation_height >= block_height) - { - debug_assert (current == original_block->hash ()); - notify_block_already_cemented_observers_callback (original_block->hash ()); - } - } - auto iterated_height = confirmation_height; - if (account_it != confirmed_iterated_pairs.cend () && account_it->second.iterated_height > iterated_height) - { - iterated_height = account_it->second.iterated_height; - } - - auto count_before_receive = receive_source_pairs.size (); - std::vector block_callback_datas_required; - auto already_traversed = iterated_height >= block_height; - if (!already_traversed) - { - collect_unconfirmed_receive_and_sources_for_account (block_height, iterated_height, block, current, account, read_transaction, receive_source_pairs, block_callback_datas_required, orig_block_callback_data, original_block); - } - - // Exit early when the processor has been stopped, otherwise this function may take a - // while (and hence keep the process running) if updating a long chain. - if (stopped) - { - break; - } - - // No longer need the read transaction - read_transaction.reset (); - - // If this adds no more open or receive blocks, then we can now confirm this account as well as the linked open/receive block - // Collect as pending any writes to the database and do them in bulk after a certain time. - auto confirmed_receives_pending = (count_before_receive != receive_source_pairs.size ()); - if (!confirmed_receives_pending) - { - preparation_data preparation_data{ block_height, confirmation_height, iterated_height, account_it, account, receive_details, already_traversed, current, block_callback_datas_required, orig_block_callback_data }; - prepare_iterated_blocks_for_cementing (preparation_data); - - if (!receive_source_pairs.empty ()) - { - // Pop from the end - receive_source_pairs.erase (receive_source_pairs.end () - 1); - } - } - else if (block_height > iterated_height) - { - if (account_it != confirmed_iterated_pairs.cend ()) - { - account_it->second.iterated_height = block_height; - } - else - { - confirmed_iterated_pairs.emplace (std::piecewise_construct, std::forward_as_tuple (account), std::forward_as_tuple (confirmation_height, block_height)); - ++confirmed_iterated_pairs_size; - } - } - - auto max_write_size_reached = (pending_writes.size () >= confirmation_height::unbounded_cutoff); - // When there are a lot of pending confirmation height blocks, it is more efficient to - // bulk some of them up to enable better write performance which becomes the bottleneck. - auto min_time_exceeded = (timer.since_start () >= batch_separate_pending_min_time); - auto finished_iterating = receive_source_pairs.empty (); - auto no_pending = awaiting_processing_size_callback () == 0; - auto should_output = finished_iterating && (no_pending || min_time_exceeded); - - auto total_pending_write_block_count = std::accumulate (pending_writes.cbegin (), pending_writes.cend (), uint64_t (0), [] (uint64_t total, conf_height_details const & receive_details_a) { - return total += receive_details_a.num_blocks_confirmed; - }); - auto force_write = total_pending_write_block_count > batch_write_size; - - if ((max_write_size_reached || should_output || force_write) && !pending_writes.empty ()) - { - if (write_database_queue.process (nano::writer::confirmation_height)) - { - auto scoped_write_guard = write_database_queue.pop (); - cement_blocks (scoped_write_guard); - } - else if (force_write) - { - // Unbounded processor has grown too large, force a write - auto scoped_write_guard = write_database_queue.wait (nano::writer::confirmation_height); - cement_blocks (scoped_write_guard); - } - } - - first_iter = false; - read_transaction.renew (); - } while ((!receive_source_pairs.empty () || current != original_block->hash ()) && !stopped); -} - -void nano::confirmation_height_unbounded::collect_unconfirmed_receive_and_sources_for_account (uint64_t block_height_a, uint64_t confirmation_height_a, std::shared_ptr const & block_a, nano::block_hash const & hash_a, nano::account const & account_a, store::read_transaction const & transaction_a, std::vector & receive_source_pairs_a, std::vector & block_callback_data_a, std::vector & orig_block_callback_data_a, std::shared_ptr original_block) -{ - debug_assert (block_a->hash () == hash_a); - auto hash (hash_a); - auto num_to_confirm = block_height_a - confirmation_height_a; - - // Handle any sends above a receive - auto is_original_block = (hash == original_block->hash ()); - auto hit_receive = false; - auto first_iter = true; - while ((num_to_confirm > 0) && !hash.is_zero () && !stopped) - { - std::shared_ptr block; - if (first_iter) - { - debug_assert (hash == hash_a); - block = block_a; - nano::lock_guard guard (block_cache_mutex); - block_cache[hash] = block_a; - } - else - { - block = get_block_and_sideband (hash, transaction_a); - } - - if (block) - { - if (block->is_receive () && ledger.block_exists (transaction_a, block->source ())) - { - if (!hit_receive && !block_callback_data_a.empty ()) - { - // Add the callbacks to the associated receive to retrieve later - debug_assert (!receive_source_pairs_a.empty ()); - auto & last_receive_details = receive_source_pairs_a.back ().receive_details; - last_receive_details->source_block_callback_data.assign (block_callback_data_a.begin (), block_callback_data_a.end ()); - block_callback_data_a.clear (); - } - - is_original_block = false; - hit_receive = true; - - auto block_height = confirmation_height_a + num_to_confirm; - receive_source_pairs_a.emplace_back (std::make_shared (account_a, hash, block_height, 1, std::vector{ hash }), block->source ()); - } - else if (is_original_block) - { - orig_block_callback_data_a.push_back (hash); - } - else - { - if (!hit_receive) - { - // This block is cemented via a recieve, as opposed to below a receive being cemented - block_callback_data_a.push_back (hash); - } - else - { - // We have hit a receive before, add the block to it - auto & last_receive_details = receive_source_pairs_a.back ().receive_details; - ++last_receive_details->num_blocks_confirmed; - last_receive_details->block_callback_data.push_back (hash); - - implicit_receive_cemented_mapping[hash] = std::weak_ptr (last_receive_details); - implicit_receive_cemented_mapping_size = implicit_receive_cemented_mapping.size (); - } - } - - hash = block->previous (); - } - - --num_to_confirm; - first_iter = false; - } -} - -void nano::confirmation_height_unbounded::prepare_iterated_blocks_for_cementing (preparation_data & preparation_data_a) -{ - auto receive_details = preparation_data_a.receive_details; - auto block_height = preparation_data_a.block_height; - if (block_height > preparation_data_a.confirmation_height) - { - // Check whether the previous block has been seen. If so, the rest of sends below have already been seen so don't count them - if (preparation_data_a.account_it != confirmed_iterated_pairs.cend ()) - { - preparation_data_a.account_it->second.confirmed_height = block_height; - if (block_height > preparation_data_a.iterated_height) - { - preparation_data_a.account_it->second.iterated_height = block_height; - } - } - else - { - confirmed_iterated_pairs.emplace (std::piecewise_construct, std::forward_as_tuple (preparation_data_a.account), std::forward_as_tuple (block_height, block_height)); - ++confirmed_iterated_pairs_size; - } - - auto num_blocks_confirmed = block_height - preparation_data_a.confirmation_height; - auto block_callback_data = preparation_data_a.block_callback_data; - if (block_callback_data.empty ()) - { - if (!receive_details) - { - block_callback_data = preparation_data_a.orig_block_callback_data; - } - else - { - debug_assert (receive_details); - - if (preparation_data_a.already_traversed && receive_details->source_block_callback_data.empty ()) - { - // We are confirming a block which has already been traversed and found no associated receive details for it. - auto & above_receive_details_w = implicit_receive_cemented_mapping[preparation_data_a.current]; - debug_assert (!above_receive_details_w.expired ()); - auto above_receive_details = above_receive_details_w.lock (); - - auto num_blocks_already_confirmed = above_receive_details->num_blocks_confirmed - (above_receive_details->height - preparation_data_a.confirmation_height); - - auto end_it = above_receive_details->block_callback_data.begin () + above_receive_details->block_callback_data.size () - (num_blocks_already_confirmed); - auto start_it = end_it - num_blocks_confirmed; - - block_callback_data.assign (start_it, end_it); - } - else - { - block_callback_data = receive_details->source_block_callback_data; - } - - auto num_to_remove = block_callback_data.size () - num_blocks_confirmed; - block_callback_data.erase (std::next (block_callback_data.rbegin (), num_to_remove).base (), block_callback_data.end ()); - receive_details->source_block_callback_data.clear (); - } - } - - pending_writes.emplace_back (preparation_data_a.account, preparation_data_a.current, block_height, num_blocks_confirmed, block_callback_data); - ++pending_writes_size; - } - - if (receive_details) - { - // Check whether the previous block has been seen. If so, the rest of sends below have already been seen so don't count them - auto const & receive_account = receive_details->account; - auto receive_account_it = confirmed_iterated_pairs.find (receive_account); - if (receive_account_it != confirmed_iterated_pairs.cend ()) - { - // Get current height - auto current_height = receive_account_it->second.confirmed_height; - receive_account_it->second.confirmed_height = receive_details->height; - auto const orig_num_blocks_confirmed = receive_details->num_blocks_confirmed; - receive_details->num_blocks_confirmed = receive_details->height - current_height; - - // Get the difference and remove the callbacks - auto block_callbacks_to_remove = orig_num_blocks_confirmed - receive_details->num_blocks_confirmed; - receive_details->block_callback_data.erase (std::next (receive_details->block_callback_data.rbegin (), block_callbacks_to_remove).base (), receive_details->block_callback_data.end ()); - debug_assert (receive_details->block_callback_data.size () == receive_details->num_blocks_confirmed); - } - else - { - confirmed_iterated_pairs.emplace (std::piecewise_construct, std::forward_as_tuple (receive_account), std::forward_as_tuple (receive_details->height, receive_details->height)); - ++confirmed_iterated_pairs_size; - } - - pending_writes.push_back (*receive_details); - ++pending_writes_size; - } -} - -void nano::confirmation_height_unbounded::cement_blocks (nano::write_guard & scoped_write_guard_a) -{ - nano::timer cemented_batch_timer; - std::vector> cemented_blocks; - auto error = false; - { - auto transaction (ledger.store.tx_begin_write ({}, { nano::tables::confirmation_height })); - cemented_batch_timer.start (); - while (!pending_writes.empty ()) - { - auto & pending = pending_writes.front (); - nano::confirmation_height_info confirmation_height_info; - ledger.store.confirmation_height.get (transaction, pending.account, confirmation_height_info); - auto confirmation_height = confirmation_height_info.height; - if (pending.height > confirmation_height) - { - auto block = ledger.block (transaction, pending.hash); - debug_assert (ledger.pruning || block != nullptr); - debug_assert (ledger.pruning || block->sideband ().height == pending.height); - - if (!block) - { - if (ledger.pruning && ledger.store.pruned.exists (transaction, pending.hash)) - { - pending_writes.erase (pending_writes.begin ()); - --pending_writes_size; - continue; - } - else - { - logger.critical (nano::log::type::conf_processor_unbounded, "Failed to write confirmation height for block {} (unbounded processor)", pending.hash.to_string ()); - - error = true; - break; - } - } - ledger.stats.add (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in, pending.height - confirmation_height); - ledger.stats.add (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed_unbounded, nano::stat::dir::in, pending.height - confirmation_height); - debug_assert (pending.num_blocks_confirmed == pending.height - confirmation_height); - confirmation_height = pending.height; - ledger.cache.cemented_count += pending.num_blocks_confirmed; - ledger.store.confirmation_height.put (transaction, pending.account, { confirmation_height, pending.hash }); - - // Reverse it so that the callbacks start from the lowest newly cemented block and move upwards - std::reverse (pending.block_callback_data.begin (), pending.block_callback_data.end ()); - - nano::lock_guard guard (block_cache_mutex); - std::transform (pending.block_callback_data.begin (), pending.block_callback_data.end (), std::back_inserter (cemented_blocks), [&block_cache = block_cache] (auto const & hash_a) { - debug_assert (block_cache.count (hash_a) == 1); - return block_cache.at (hash_a); - }); - } - pending_writes.erase (pending_writes.begin ()); - --pending_writes_size; - } - } - - auto time_spent_cementing = cemented_batch_timer.since_start ().count (); - - scoped_write_guard_a.release (); - notify_observers_callback (cemented_blocks); - release_assert (!error); - - debug_assert (pending_writes.empty ()); - debug_assert (pending_writes_size == 0); - timer.restart (); -} - -std::shared_ptr nano::confirmation_height_unbounded::get_block_and_sideband (nano::block_hash const & hash_a, store::transaction const & transaction_a) -{ - nano::lock_guard guard (block_cache_mutex); - auto block_cache_it = block_cache.find (hash_a); - if (block_cache_it != block_cache.cend ()) - { - return block_cache_it->second; - } - else - { - auto block = ledger.block (transaction_a, hash_a); - block_cache.emplace (hash_a, block); - return block; - } -} - -bool nano::confirmation_height_unbounded::pending_empty () const -{ - return pending_writes.empty (); -} - -void nano::confirmation_height_unbounded::clear_process_vars () -{ - // Separate blocks which are pending confirmation height can be batched by a minimum processing time (to improve lmdb disk write performance), - // so make sure the slate is clean when a new batch is starting. - confirmed_iterated_pairs.clear (); - confirmed_iterated_pairs_size = 0; - implicit_receive_cemented_mapping.clear (); - implicit_receive_cemented_mapping_size = 0; - { - nano::lock_guard guard (block_cache_mutex); - block_cache.clear (); - } -} - -bool nano::confirmation_height_unbounded::has_iterated_over_block (nano::block_hash const & hash_a) const -{ - nano::lock_guard guard (block_cache_mutex); - return block_cache.count (hash_a) == 1; -} - -uint64_t nano::confirmation_height_unbounded::block_cache_size () const -{ - nano::lock_guard guard (block_cache_mutex); - return block_cache.size (); -} - -nano::confirmation_height_unbounded::conf_height_details::conf_height_details (nano::account const & account_a, nano::block_hash const & hash_a, uint64_t height_a, uint64_t num_blocks_confirmed_a, std::vector const & block_callback_data_a) : - account (account_a), - hash (hash_a), - height (height_a), - num_blocks_confirmed (num_blocks_confirmed_a), - block_callback_data (block_callback_data_a) -{ -} - -nano::confirmation_height_unbounded::receive_source_pair::receive_source_pair (std::shared_ptr const & receive_details_a, const block_hash & source_a) : - receive_details (receive_details_a), - source_hash (source_a) -{ -} - -nano::confirmation_height_unbounded::confirmed_iterated_pair::confirmed_iterated_pair (uint64_t confirmed_height_a, uint64_t iterated_height_a) : - confirmed_height (confirmed_height_a), - iterated_height (iterated_height_a) -{ -} - -std::unique_ptr nano::collect_container_info (confirmation_height_unbounded & confirmation_height_unbounded, std::string const & name_a) -{ - auto composite = std::make_unique (name_a); - composite->add_component (std::make_unique (container_info{ "confirmed_iterated_pairs", confirmation_height_unbounded.confirmed_iterated_pairs_size, sizeof (decltype (confirmation_height_unbounded.confirmed_iterated_pairs)::value_type) })); - composite->add_component (std::make_unique (container_info{ "pending_writes", confirmation_height_unbounded.pending_writes_size, sizeof (decltype (confirmation_height_unbounded.pending_writes)::value_type) })); - composite->add_component (std::make_unique (container_info{ "implicit_receive_cemented_mapping", confirmation_height_unbounded.implicit_receive_cemented_mapping_size, sizeof (decltype (confirmation_height_unbounded.implicit_receive_cemented_mapping)::value_type) })); - composite->add_component (std::make_unique (container_info{ "block_cache", confirmation_height_unbounded.block_cache_size (), sizeof (decltype (confirmation_height_unbounded.block_cache)::value_type) })); - return composite; -} diff --git a/nano/node/confirmation_height_unbounded.hpp b/nano/node/confirmation_height_unbounded.hpp deleted file mode 100644 index ea3e7e52..00000000 --- a/nano/node/confirmation_height_unbounded.hpp +++ /dev/null @@ -1,114 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace nano -{ -class ledger; -class write_database_queue; -class write_guard; - -class confirmation_height_unbounded final -{ -public: - confirmation_height_unbounded (nano::ledger &, nano::write_database_queue &, std::chrono::milliseconds batch_separate_pending_min_time, nano::logger &, std::atomic & stopped, uint64_t & batch_write_size, std::function> const &)> const & cemented_callback, std::function const & already_cemented_callback, std::function const & awaiting_processing_size_query); - - bool pending_empty () const; - void clear_process_vars (); - void process (std::shared_ptr original_block); - void cement_blocks (nano::write_guard &); - bool has_iterated_over_block (nano::block_hash const &) const; - -private: - class confirmed_iterated_pair - { - public: - confirmed_iterated_pair (uint64_t confirmed_height_a, uint64_t iterated_height_a); - uint64_t confirmed_height; - uint64_t iterated_height; - }; - - class conf_height_details final - { - public: - conf_height_details (nano::account const &, nano::block_hash const &, uint64_t, uint64_t, std::vector const &); - - nano::account account; - nano::block_hash hash; - uint64_t height; - uint64_t num_blocks_confirmed; - std::vector block_callback_data; - std::vector source_block_callback_data; - }; - - class receive_source_pair final - { - public: - receive_source_pair (std::shared_ptr const &, nano::block_hash const &); - - std::shared_ptr receive_details; - nano::block_hash source_hash; - }; - - // All of the atomic variables here just track the size for use in collect_container_info. - // This is so that no mutexes are needed during the algorithm itself, which would otherwise be needed - // for the sake of a rarely used RPC call for debugging purposes. As such the sizes are not being acted - // upon in any way (does not synchronize with any other data). - // This allows the load and stores to use relaxed atomic memory ordering. - std::unordered_map confirmed_iterated_pairs; - nano::relaxed_atomic_integral confirmed_iterated_pairs_size{ 0 }; - std::shared_ptr get_block_and_sideband (nano::block_hash const &, store::transaction const &); - std::deque pending_writes; - nano::relaxed_atomic_integral pending_writes_size{ 0 }; - std::unordered_map> implicit_receive_cemented_mapping; - nano::relaxed_atomic_integral implicit_receive_cemented_mapping_size{ 0 }; - - mutable nano::mutex block_cache_mutex; - std::unordered_map> block_cache; - uint64_t block_cache_size () const; - - nano::timer timer; - - class preparation_data final - { - public: - uint64_t block_height; - uint64_t confirmation_height; - uint64_t iterated_height; - decltype (confirmed_iterated_pairs.begin ()) account_it; - nano::account const & account; - std::shared_ptr receive_details; - bool already_traversed; - nano::block_hash const & current; - std::vector const & block_callback_data; - std::vector const & orig_block_callback_data; - }; - - void collect_unconfirmed_receive_and_sources_for_account (uint64_t, uint64_t, std::shared_ptr const &, nano::block_hash const &, nano::account const &, store::read_transaction const &, std::vector &, std::vector &, std::vector &, std::shared_ptr original_block); - void prepare_iterated_blocks_for_cementing (preparation_data &); - - nano::ledger & ledger; - nano::write_database_queue & write_database_queue; - std::chrono::milliseconds batch_separate_pending_min_time; - nano::logger & logger; - std::atomic & stopped; - uint64_t & batch_write_size; - - std::function> const &)> notify_observers_callback; - std::function notify_block_already_cemented_observers_callback; - std::function awaiting_processing_size_callback; - - friend class confirmation_height_dynamic_algorithm_no_transition_while_pending_Test; - friend std::unique_ptr collect_container_info (confirmation_height_unbounded &, std::string const & name_a); -}; - -std::unique_ptr collect_container_info (confirmation_height_unbounded &, std::string const & name_a); -} diff --git a/nano/node/json_handler.cpp b/nano/node/json_handler.cpp index fe217b75..ccec370e 100644 --- a/nano/node/json_handler.cpp +++ b/nano/node/json_handler.cpp @@ -1206,7 +1206,7 @@ void nano::json_handler::block_confirm () if (!node.ledger.block_confirmed (transaction, hash)) { // Start new confirmation for unconfirmed (or not being confirmed) block - if (!node.confirmation_height_processor.exists (hash)) + if (!node.confirming_set.exists (hash)) { node.start_election (std::move (block_l)); } diff --git a/nano/node/node.cpp b/nano/node/node.cpp index a032e60b..da3a2f0e 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -466,7 +466,7 @@ nano::node::node (std::shared_ptr io_ctx_a, std::filesy std::exit (1); } } - confirmation_height_processor.cemented_observers.add ([this] (auto const & block) { + confirming_set.cemented_observers.add ([this] (auto const & block) { if (block->is_send ()) { auto transaction = store.tx_begin_read (); @@ -570,7 +570,7 @@ std::unique_ptr nano::collect_container_info (no composite->add_component (node.history.collect_container_info ("history")); composite->add_component (node.block_uniquer.collect_container_info ("block_uniquer")); composite->add_component (node.vote_uniquer.collect_container_info ("vote_uniquer")); - composite->add_component (node.confirmation_height_processor.collect_container_info ("confirmation_queue")); + composite->add_component (node.confirming_set.collect_container_info ("confirming_set")); composite->add_component (collect_container_info (node.distributed_work, "distributed_work")); composite->add_component (collect_container_info (node.aggregator, "request_aggregator")); composite->add_component (node.scheduler.collect_container_info ("election_scheduler")); @@ -681,7 +681,7 @@ void nano::node::start () active.start (); generator.start (); final_generator.start (); - confirmation_height_processor.start (); + confirming_set.start (); scheduler.start (); backlog.start (); bootstrap_server.start (); @@ -722,7 +722,7 @@ void nano::node::stop () active.stop (); generator.stop (); final_generator.stop (); - confirmation_height_processor.stop (); + confirming_set.stop (); telemetry.stop (); websocket.stop (); bootstrap_server.stop (); @@ -1188,7 +1188,7 @@ bool nano::node::block_confirmed (nano::block_hash const & hash_a) bool nano::node::block_confirmed_or_being_confirmed (nano::store::transaction const & transaction, nano::block_hash const & hash_a) { - return confirmation_height_processor.exists (hash_a) || ledger.block_confirmed (transaction, hash_a); + return confirming_set.exists (hash_a) || ledger.block_confirmed (transaction, hash_a); } bool nano::node::block_confirmed_or_being_confirmed (nano::block_hash const & hash_a) @@ -1260,7 +1260,7 @@ void nano::node::process_confirmed (nano::election_status const & status_a, uint { logger.trace (nano::log::type::node, nano::log::detail::process_confirmed, nano::log::arg{ "block", block_l }); - confirmation_height_processor.add (block_l->hash ()); + confirming_set.add (block_l->hash ()); } else if (iteration_a < num_iters) { diff --git a/nano/node/node.hpp b/nano/node/node.hpp index 8c1a0476..53ba1f69 100644 --- a/nano/node/node.hpp +++ b/nano/node/node.hpp @@ -168,8 +168,8 @@ public: nano::node_observers observers; nano::port_mapping port_mapping; nano::block_processor block_processor; - std::unique_ptr confirmation_height_processor_impl; - nano::confirming_set & confirmation_height_processor; + std::unique_ptr confirming_set_impl; + nano::confirming_set & confirming_set; std::unique_ptr active_impl; nano::active_transactions & active; nano::online_reps online_reps; diff --git a/nano/node/wallet.cpp b/nano/node/wallet.cpp index a322b003..696d7b4b 100644 --- a/nano/node/wallet.cpp +++ b/nano/node/wallet.cpp @@ -1198,7 +1198,7 @@ bool nano::wallet::search_receivable (store::transaction const & wallet_transact // Receive confirmed block receive_async (hash, representative, amount, account, [] (std::shared_ptr const &) {}); } - else if (!wallets.node.confirmation_height_processor.exists (hash)) + else if (!wallets.node.confirming_set.exists (hash)) { auto block = wallets.node.ledger.block (block_transaction, hash); if (block) diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index 66c10fac..284bea02 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -5820,7 +5820,7 @@ TEST (rpc, block_confirmed) ASSERT_TRUE (nano::test::start_elections (system, *node, { send }, true)); // Wait until the confirmation height has been set - ASSERT_TIMELY (5s, node->ledger.block_confirmed (node->store.tx_begin_read (), send->hash ()) && !node->confirmation_height_processor.exists (send->hash ())); + ASSERT_TIMELY (5s, node->ledger.block_confirmed (node->store.tx_begin_read (), send->hash ()) && !node->confirming_set.exists (send->hash ())); // Requesting confirmation for this should now succeed request.put ("hash", send->hash ().to_string ()); diff --git a/nano/secure/common.hpp b/nano/secure/common.hpp index bc6f50a2..cca99a87 100644 --- a/nano/secure/common.hpp +++ b/nano/secure/common.hpp @@ -341,12 +341,5 @@ public: nano::bootstrap_constants bootstrap; }; -enum class confirmation_height_mode -{ - automatic, - unbounded, - bounded -}; - nano::wallet_id random_wallet_id (); } diff --git a/nano/slow_test/node.cpp b/nano/slow_test/node.cpp index 2c1ff3c9..f9f3d57c 100644 --- a/nano/slow_test/node.cpp +++ b/nano/slow_test/node.cpp @@ -975,10 +975,10 @@ TEST (confirmation_height, dynamic_algorithm) } } - node->confirmation_height_processor.add (state_blocks.front ()->hash ()); + node->confirming_set.add (state_blocks.front ()->hash ()); ASSERT_TIMELY_EQ (20s, node->ledger.cache.cemented_count, 2); - node->confirmation_height_processor.add (latest_genesis->hash ()); + node->confirming_set.add (latest_genesis->hash ()); ASSERT_TIMELY_EQ (20s, node->ledger.cache.cemented_count, num_blocks + 1); @@ -1144,7 +1144,7 @@ TEST (confirmation_height, many_accounts_send_receive_self_no_elections) nano::block_hash block_hash_being_processed{ 0 }; nano::write_database_queue write_queue{ false }; - nano::confirming_set confirmation_height_processor{ ledger, write_queue }; + nano::confirming_set confirming_set{ ledger, write_queue }; auto const num_accounts = 100000; @@ -1189,7 +1189,7 @@ TEST (confirmation_height, many_accounts_send_receive_self_no_elections) for (auto & open_block : open_blocks) { - confirmation_height_processor.add (open_block->hash ()); + confirming_set.add (open_block->hash ()); } system.deadline_set (1000s); @@ -1240,8 +1240,8 @@ TEST (confirmation_height, many_accounts_send_receive_self_no_elections) // Now send and receive to self for (int i = 0; i < open_blocks.size (); ++i) { - confirmation_height_processor.add (send_blocks[i]->hash ()); - confirmation_height_processor.add (receive_blocks[i]->hash ()); + confirming_set.add (send_blocks[i]->hash ()); + confirming_set.add (receive_blocks[i]->hash ()); } system.deadline_set (1000s); @@ -1251,7 +1251,7 @@ TEST (confirmation_height, many_accounts_send_receive_self_no_elections) ASSERT_NO_ERROR (system.poll ()); } - while (confirmation_height_processor.size () > 0) + while (confirming_set.size () > 0) { ASSERT_NO_ERROR (system.poll ()); } @@ -2078,7 +2078,7 @@ TEST (node, wallet_create_block_confirm_conflicts) election->force_confirm (); } - ASSERT_TIMELY (120s, node->ledger.block_confirmed (node->store.tx_begin_read (), latest) && node->confirmation_height_processor.size () == 0); + ASSERT_TIMELY (120s, node->ledger.block_confirmed (node->store.tx_begin_read (), latest) && node->confirming_set.size () == 0); done = true; t.join (); }