From 5245414dee52924b5624d7a5df9bf77a98e6f40b Mon Sep 17 00:00:00 2001 From: Sergey Kroshnin Date: Mon, 14 Jan 2019 16:06:05 +0300 Subject: [PATCH] List of rolled back blocks in block_processor (#1581) * List of rolled back blocks in block_processor With limit 1024 * Update node.cpp * Make rolled_back_max static const --- nano/node/node.cpp | 19 +++++++++++++++++-- nano/node/node.hpp | 13 +++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/nano/node/node.cpp b/nano/node/node.cpp index 96a28535..dccac56f 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -1232,8 +1232,9 @@ void nano::block_processor::add (std::shared_ptr block_a, std::chro if (!nano::work_validate (block_a->root (), block_a->block_work ())) { { + auto hash (block_a->hash ()); std::lock_guard lock (mutex); - if (blocks_hashes.find (block_a->hash ()) == blocks_hashes.end ()) + if (blocks_hashes.find (hash) == blocks_hashes.end () && rolled_back.get<1> ().find (hash) == rolled_back.get<1> ().end ()) { if (block_a->type () == nano::block_type::state && !node.ledger.is_epoch_link (block_a->link ())) { @@ -1243,7 +1244,7 @@ void nano::block_processor::add (std::shared_ptr block_a, std::chro { blocks.push_back (std::make_pair (block_a, origination)); } - blocks_hashes.insert (block_a->hash ()); + blocks_hashes.insert (hash); } condition.notify_all (); } @@ -1431,6 +1432,20 @@ void nano::block_processor::process_batch (std::unique_lock & lock_a // Replace our block with the winner and roll back any dependent blocks BOOST_LOG (node.log) << boost::str (boost::format ("Rolling back %1% and replacing with %2%") % successor->hash ().to_string () % hash.to_string ()); node.ledger.rollback (transaction, successor->hash ()); + lock_a.lock (); + // Prevent rolled back blocks second insertion + auto inserted (rolled_back.insert (nano::rolled_hash{ std::chrono::steady_clock::now (), successor->hash () })); + if (inserted.second) + { + // Possible election winner change + rolled_back.get<1> ().erase (hash); + // Prevent overflow + if (rolled_back.size () > rolled_back_max) + { + rolled_back.erase (rolled_back.begin ()); + } + } + lock_a.unlock (); } } /* Forced state blocks are not validated in verify_state_blocks () function diff --git a/nano/node/node.hpp b/nano/node/node.hpp index 2a161a7b..ca99d68d 100644 --- a/nano/node/node.hpp +++ b/nano/node/node.hpp @@ -410,6 +410,12 @@ private: std::condition_variable condition; std::thread thread; }; +class rolled_hash +{ +public: + std::chrono::steady_clock::time_point time; + nano::block_hash hash; +}; // Processing blocks is a potentially long IO operation // This class isolates block insertion from other operations like servicing network operations class block_processor @@ -438,6 +444,13 @@ private: std::deque, std::chrono::steady_clock::time_point>> blocks; std::unordered_set blocks_hashes; std::deque> forced; + boost::multi_index_container< + nano::rolled_hash, + boost::multi_index::indexed_by< + boost::multi_index::ordered_non_unique>, + boost::multi_index::hashed_unique>>> + rolled_back; + static size_t const rolled_back_max = 1024; std::condition_variable condition; nano::node & node; nano::vote_generator generator;