Unresolved forks during initial bootstrap (#2833)

* Unresolved forks during initial bootstrap
* Additional check for unchecked info arrival/modification time
Co-authored-by: Sergey Kroshnin <sergiysw@gmail.com>
This commit is contained in:
Wesley Shillingford 2020-07-08 15:11:58 +01:00 committed by GitHub
commit d120985c3b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 4 deletions

View file

@ -866,6 +866,47 @@ TEST (bootstrap_processor, multiple_attempts)
node2->stop ();
}
TEST (bootstrap_processor, bootstrap_fork)
{
nano::system system;
nano::node_config config (nano::get_available_port (), system.logging);
config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
nano::node_flags node_flags;
node_flags.disable_bootstrap_bulk_push_client = true;
node_flags.disable_lazy_bootstrap = true;
node_flags.disable_legacy_bootstrap = true;
auto node0 (system.add_node (config, node_flags));
nano::keypair key;
auto send (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, node0->latest (nano::test_genesis_key.pub), nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (node0->latest (nano::test_genesis_key.pub))));
ASSERT_EQ (nano::process_result::progress, node0->process (*send).code);
// Confirm send block to vote later
node0->block_confirm (send);
{
auto election = node0->active.election (send->qualified_root ());
ASSERT_NE (nullptr, election);
nano::lock_guard<std::mutex> guard (node0->active.mutex);
election->confirm_once ();
}
ASSERT_TIMELY (2s, node0->block_confirmed (send->hash ()));
node0->active.erase (*send);
auto open_work (*system.work.generate (key.pub));
auto open (std::make_shared<nano::state_block> (key.pub, 0, key.pub, nano::Gxrb_ratio, send->hash (), key.prv, key.pub, open_work));
ASSERT_EQ (nano::process_result::progress, node0->process (*open).code);
system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv);
// Create forked node
config.peering_port = nano::get_available_port ();
node_flags.disable_legacy_bootstrap = false;
auto node1 (system.add_node (config, node_flags));
ASSERT_EQ (nano::process_result::progress, node1->process (*send).code);
auto open_fork (std::make_shared<nano::state_block> (key.pub, 0, nano::test_genesis_key.pub, nano::Gxrb_ratio, send->hash (), key.prv, key.pub, open_work));
ASSERT_EQ (nano::process_result::progress, node1->process (*open_fork).code);
// Resolve fork
node1->bootstrap_initiator.bootstrap (node0->network.endpoint ());
ASSERT_TIMELY (10s, node1->ledger.block_exists (open->hash ()));
ASSERT_FALSE (node1->ledger.block_exists (open_fork->hash ()));
node1->stop ();
}
TEST (frontier_req_response, DISABLED_destruction)
{
{

View file

@ -432,7 +432,7 @@ nano::process_return nano::block_processor::process_one (nano::write_transaction
}
case nano::process_result::fork:
{
node.process_fork (transaction_a, info_a.block);
node.process_fork (transaction_a, info_a.block, info_a.modified);
node.stats.inc (nano::stat::type::ledger, nano::stat::detail::fork);
if (node.config.logging.ledger_logging ())
{

View file

@ -518,13 +518,13 @@ bool nano::node::copy_with_compaction (boost::filesystem::path const & destinati
return store.copy_db (destination);
}
void nano::node::process_fork (nano::transaction const & transaction_a, std::shared_ptr<nano::block> block_a)
void nano::node::process_fork (nano::transaction const & transaction_a, std::shared_ptr<nano::block> block_a, uint64_t modified_a)
{
auto root (block_a->root ());
if (!store.block_exists (transaction_a, block_a->type (), block_a->hash ()) && store.root_exists (transaction_a, block_a->root ()))
{
std::shared_ptr<nano::block> ledger_block (ledger.forked_block (transaction_a, *block_a));
if (ledger_block && !block_confirmed_or_being_confirmed (transaction_a, ledger_block->hash ()) && ledger.can_vote (transaction_a, *ledger_block))
if (ledger_block && !block_confirmed_or_being_confirmed (transaction_a, ledger_block->hash ()) && (ledger.can_vote (transaction_a, *ledger_block) || modified_a < nano::seconds_since_epoch () - 300 || !block_arrival.recent (block_a->hash ())))
{
std::weak_ptr<nano::node> this_w (shared_from_this ());
auto election = active.insert (ledger_block, boost::none, [this_w, root](std::shared_ptr<nano::block>) {

View file

@ -139,7 +139,7 @@ public:
void block_confirm (std::shared_ptr<nano::block>);
bool block_confirmed (nano::block_hash const &);
bool block_confirmed_or_being_confirmed (nano::transaction const &, nano::block_hash const &);
void process_fork (nano::transaction const &, std::shared_ptr<nano::block>);
void process_fork (nano::transaction const &, std::shared_ptr<nano::block>, uint64_t);
void do_rpc_callback (boost::asio::ip::tcp::resolver::iterator i_a, std::string const &, uint16_t, std::shared_ptr<std::string>, std::shared_ptr<std::string>, std::shared_ptr<boost::asio::ip::tcp::resolver>);
nano::uint128_t delta () const;
void ongoing_online_weight_calculation ();