diff --git a/nano/node/blockprocessor.cpp b/nano/node/blockprocessor.cpp index 7fabb21e10..c50532dc8e 100644 --- a/nano/node/blockprocessor.cpp +++ b/nano/node/blockprocessor.cpp @@ -123,6 +123,40 @@ std::optional nano::block_processor::add_blocking (std::sh return result; } +void nano::block_processor::rollback_competitor (nano::write_transaction const & transaction, nano::block const & block) +{ + auto hash = block.hash (); + auto successor = node.ledger.successor (transaction, block.qualified_root ()); + if (successor != nullptr && successor->hash () != hash) + { + // Replace our block with the winner and roll back any dependent blocks + if (node.config.logging.ledger_rollback_logging ()) + { + node.logger.always_log (boost::str (boost::format ("Rolling back %1% and replacing with %2%") % successor->hash ().to_string () % hash.to_string ())); + } + std::vector> rollback_list; + if (node.ledger.rollback (transaction, successor->hash (), rollback_list)) + { + node.stats.inc (nano::stat::type::ledger, nano::stat::detail::rollback_failed); + node.logger.always_log (nano::severity_level::error, boost::str (boost::format ("Failed to roll back %1% because it or a successor was confirmed") % successor->hash ().to_string ())); + } + else if (node.config.logging.ledger_rollback_logging ()) + { + node.logger.always_log (boost::str (boost::format ("%1% blocks rolled back") % rollback_list.size ())); + } + // Deleting from votes cache, stop active transaction + for (auto & i : rollback_list) + { + node.history.erase (i->root ()); + // Stop all rolled back active transactions except initial + if (i->hash () != successor->hash ()) + { + node.active.erase (*i); + } + } + } +} + void nano::block_processor::force (std::shared_ptr const & block_a) { { @@ -266,35 +300,7 @@ auto nano::block_processor::process_batch (nano::unique_lock & lock lock_a.unlock (); if (force) { - auto successor = node.ledger.successor (transaction, block->qualified_root ()); - if (successor != nullptr && successor->hash () != hash) - { - // Replace our block with the winner and roll back any dependent blocks - if (node.config.logging.ledger_rollback_logging ()) - { - node.logger.always_log (boost::str (boost::format ("Rolling back %1% and replacing with %2%") % successor->hash ().to_string () % hash.to_string ())); - } - std::vector> rollback_list; - if (node.ledger.rollback (transaction, successor->hash (), rollback_list)) - { - node.stats.inc (nano::stat::type::ledger, nano::stat::detail::rollback_failed); - node.logger.always_log (nano::severity_level::error, boost::str (boost::format ("Failed to roll back %1% because it or a successor was confirmed") % successor->hash ().to_string ())); - } - else if (node.config.logging.ledger_rollback_logging ()) - { - node.logger.always_log (boost::str (boost::format ("%1% blocks rolled back") % rollback_list.size ())); - } - // Deleting from votes cache, stop active transaction - for (auto & i : rollback_list) - { - node.history.erase (i->root ()); - // Stop all rolled back active transactions except initial - if (i->hash () != successor->hash ()) - { - node.active.erase (*i); - } - } - } + rollback_competitor (transaction, *block); } number_of_blocks_processed++; auto result = process_one (transaction, block, force); diff --git a/nano/node/blockprocessor.hpp b/nano/node/blockprocessor.hpp index 91861051e8..0f995734aa 100644 --- a/nano/node/blockprocessor.hpp +++ b/nano/node/blockprocessor.hpp @@ -54,6 +54,8 @@ class block_processor final blocking_observer blocking; private: + // Roll back block in the ledger that conflicts with 'block' + void rollback_competitor (nano::write_transaction const & transaction, nano::block const & block); nano::process_return process_one (nano::write_transaction const &, std::shared_ptr block, bool const = false); void queue_unchecked (nano::write_transaction const &, nano::hash_or_account const &); std::deque process_batch (nano::unique_lock &);