diff --git a/nano/core_test/confirmation_height.cpp b/nano/core_test/confirmation_height.cpp index bf913bca0..5ac746db1 100644 --- a/nano/core_test/confirmation_height.cpp +++ b/nano/core_test/confirmation_height.cpp @@ -1560,7 +1560,7 @@ TEST (confirmation_height, callback_confirmed_history) ASSERT_NE (nullptr, election); election->force_confirm (); ASSERT_TIMELY (10s, node->active.size () == 0); - ASSERT_EQ (0, node->active.list_recently_cemented ().size ()); + ASSERT_EQ (0, node->active.recently_cemented.list ().size ()); { nano::lock_guard guard (node->active.mutex); ASSERT_EQ (0, node->active.blocks.size ()); @@ -1583,7 +1583,7 @@ TEST (confirmation_height, callback_confirmed_history) ASSERT_TIMELY (10s, node->active.size () == 0); ASSERT_TIMELY (10s, node->stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::active_quorum, nano::stat::dir::out) == 1); - ASSERT_EQ (1, node->active.list_recently_cemented ().size ()); + ASSERT_EQ (1, node->active.recently_cemented.list ().size ()); ASSERT_EQ (0, node->active.blocks.size ()); // Confirm the callback is not called under this circumstance diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index c5a9fb2f9..4ac92d983 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -2238,7 +2238,7 @@ TEST (node, block_confirm) node2.block_confirm (send1_copy); auto election = node2.active.election (send1_copy->qualified_root ()); ASSERT_NE (nullptr, election); - ASSERT_TIMELY (10s, node1.active.list_recently_cemented ().size () == 1); + ASSERT_TIMELY (10s, node1.active.recently_cemented.list ().size () == 1); } } diff --git a/nano/node/active_transactions.cpp b/nano/node/active_transactions.cpp index ef5b55fc4..376dcfd35 100644 --- a/nano/node/active_transactions.cpp +++ b/nano/node/active_transactions.cpp @@ -21,6 +21,7 @@ nano::active_transactions::active_transactions (nano::node & node_a, nano::confi generator{ node_a.config, node_a.ledger, node_a.wallets, node_a.vote_processor, node_a.history, node_a.network, node_a.stats, false }, final_generator{ node_a.config, node_a.ledger, node_a.wallets, node_a.vote_processor, node_a.history, node_a.network, node_a.stats, true }, recently_confirmed{ 65536 }, + recently_cemented{ node.config.confirmation_history_size }, election_time_to_live{ node_a.network_params.network.is_dev_network () ? 0s : 2s }, thread ([this] () { nano::thread_role::set (nano::thread_role::name::request_loop); @@ -88,7 +89,7 @@ void nano::active_transactions::block_cemented_callback (std::shared_ptr election_lk (election->mutex); auto status_l = election->status; election_lk.unlock (); - add_recently_cemented (status_l); + recently_cemented.put (status_l); auto destination (block_a->link ().is_zero () ? block_a->destination () : block_a->link ().as_account ()); node.receive_confirmed (transaction, hash, destination); nano::account account{}; @@ -531,22 +532,6 @@ std::shared_ptr nano::active_transactions::winner (nano::block_hash return result; } -std::deque nano::active_transactions::list_recently_cemented () -{ - nano::lock_guard lock (mutex); - return recently_cemented; -} - -void nano::active_transactions::add_recently_cemented (nano::election_status const & status_a) -{ - nano::lock_guard guard (mutex); - recently_cemented.push_back (status_a); - if (recently_cemented.size () > node.config.confirmation_history_size) - { - recently_cemented.pop_front (); - } -} - void nano::active_transactions::erase (nano::block const & block_a) { erase (block_a.qualified_root ()); @@ -873,7 +858,7 @@ std::unique_ptr nano::collect_container_info (ac composite->add_component (std::make_unique (container_info{ "blocks", blocks_count, sizeof (decltype (active_transactions.blocks)::value_type) })); composite->add_component (std::make_unique (container_info{ "election_winner_details", active_transactions.election_winner_details_size (), sizeof (decltype (active_transactions.election_winner_details)::value_type) })); composite->add_component (std::make_unique (container_info{ "recently_confirmed", recently_confirmed_count, sizeof (decltype (active_transactions.recently_confirmed.confirmed)::value_type) })); - composite->add_component (std::make_unique (container_info{ "recently_cemented", recently_cemented_count, sizeof (decltype (active_transactions.recently_cemented)::value_type) })); + composite->add_component (std::make_unique (container_info{ "recently_cemented", recently_cemented_count, sizeof (decltype (active_transactions.recently_cemented.cemented)::value_type) })); composite->add_component (std::make_unique (container_info{ "inactive_votes_cache", active_transactions.inactive_votes_cache_size (), sizeof (nano::gap_information) })); composite->add_component (collect_container_info (active_transactions.generator, "generator")); return composite; @@ -932,4 +917,35 @@ nano::recently_confirmed_cache::entry_t nano::recently_confirmed_cache::back () { nano::lock_guard guard{ mutex }; return confirmed.back (); +} + +/* + * class recently_cemented + */ + +nano::recently_cemented_cache::recently_cemented_cache (std::size_t max_size_a) : + max_size{ max_size_a } +{ +} + +void nano::recently_cemented_cache::put (const nano::election_status & status) +{ + nano::lock_guard guard{ mutex }; + cemented.push_back (status); + if (cemented.size () > max_size) + { + cemented.pop_front (); + } +} + +nano::recently_cemented_cache::queue_t nano::recently_cemented_cache::list () const +{ + nano::lock_guard guard{ mutex }; + return cemented; +} + +std::size_t nano::recently_cemented_cache::size () const +{ + nano::lock_guard guard{ mutex }; + return cemented.size (); } \ No newline at end of file diff --git a/nano/node/active_transactions.hpp b/nano/node/active_transactions.hpp index bdfc9b7fe..78f42c6df 100644 --- a/nano/node/active_transactions.hpp +++ b/nano/node/active_transactions.hpp @@ -79,6 +79,29 @@ private: friend std::unique_ptr collect_container_info (active_transactions &, std::string const &); }; +/* + * Helper container for storing recently cemented elections (a block from election might be confirmed but not yet cemented by confirmation height processor) + */ +class recently_cemented_cache final +{ +public: + using queue_t = std::deque; + + explicit recently_cemented_cache (std::size_t max_size); + + void put (nano::election_status const &); + queue_t list () const; + std::size_t size () const; + +private: + queue_t cemented; + std::size_t const max_size; + + mutable nano::mutex mutex; + + friend std::unique_ptr collect_container_info (active_transactions &, std::string const &); +}; + class election_insertion_result final { public: @@ -147,10 +170,7 @@ public: std::function vacancy_update{ [] () {} }; std::unordered_map> blocks; - std::deque list_recently_cemented (); - std::deque recently_cemented; - void add_recently_cemented (nano::election_status const &); void add_inactive_votes_cache (nano::unique_lock &, nano::block_hash const &, nano::account const &, uint64_t const); // Inserts an election if conditions are met void trigger_inactive_votes_cache_election (std::shared_ptr const &); @@ -169,6 +189,7 @@ public: nano::vote_generator final_generator; recently_confirmed_cache recently_confirmed; + recently_cemented_cache recently_cemented; #ifdef MEMORY_POOL_DISABLED using allocator = std::allocator; diff --git a/nano/node/json_handler.cpp b/nano/node/json_handler.cpp index d8ea6f7bf..fd7d0fca6 100644 --- a/nano/node/json_handler.cpp +++ b/nano/node/json_handler.cpp @@ -1187,7 +1187,7 @@ void nano::json_handler::block_confirm () { // Add record in confirmation history for confirmed block nano::election_status status{ block_l, 0, 0, std::chrono::duration_cast (std::chrono::system_clock::now ().time_since_epoch ()), std::chrono::duration_values::zero (), 0, 1, 0, nano::election_status_type::active_confirmation_height }; - node.active.add_recently_cemented (status); + node.active.recently_cemented.put (status); // Trigger callback for confirmed block node.block_arrival.add (hash); auto account (node.ledger.account (transaction, hash)); @@ -2006,7 +2006,7 @@ void nano::json_handler::confirmation_history () } if (!ec) { - for (auto const & status : node.active.list_recently_cemented ()) + for (auto const & status : node.active.recently_cemented.list ()) { if (hash.is_zero () || status.winner->hash () == hash) { diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index 6989c7b75..1ac346018 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -5875,9 +5875,9 @@ TEST (rpc, confirmation_history) auto node = add_ipc_enabled_node (system); nano::keypair key; system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); - ASSERT_TRUE (node->active.list_recently_cemented ().empty ()); + ASSERT_TRUE (node->active.recently_cemented.list ().empty ()); auto block (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key.pub, nano::Gxrb_ratio)); - ASSERT_TIMELY (10s, !node->active.list_recently_cemented ().empty ()); + ASSERT_TIMELY (10s, !node->active.recently_cemented.list ().empty ()); auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; request.put ("action", "confirmation_history"); @@ -5906,11 +5906,11 @@ TEST (rpc, confirmation_history_hash) auto node = add_ipc_enabled_node (system); nano::keypair key; system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); - ASSERT_TRUE (node->active.list_recently_cemented ().empty ()); + ASSERT_TRUE (node->active.recently_cemented.list ().empty ()); auto send1 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key.pub, nano::Gxrb_ratio)); auto send2 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key.pub, nano::Gxrb_ratio)); auto send3 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key.pub, nano::Gxrb_ratio)); - ASSERT_TIMELY (10s, node->active.list_recently_cemented ().size () == 3); + ASSERT_TIMELY (10s, node->active.recently_cemented.list ().size () == 3); auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; request.put ("action", "confirmation_history"); @@ -5995,7 +5995,7 @@ TEST (rpc, block_confirm_confirmed) auto response (wait_response (system, rpc_ctx, request)); ASSERT_EQ ("1", response.get ("started")); // Check confirmation history - auto confirmed (node->active.list_recently_cemented ()); + auto confirmed (node->active.recently_cemented.list ()); ASSERT_EQ (1, confirmed.size ()); ASSERT_EQ (nano::dev::genesis->hash (), confirmed.begin ()->winner->hash ()); // Check callback