diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index 7195f823..6780d783 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -2747,6 +2747,55 @@ TEST (node, local_votes_cache_generate_new_vote) ASSERT_TIMELY (3s, 3 == node.stats.count (nano::stat::type::message, nano::stat::detail::confirm_ack, nano::stat::dir::out)); } +TEST (node, local_votes_cache_fork) +{ + nano::system system; + nano::node_flags node_flags; + node_flags.disable_bootstrap_bulk_push_client = true; + node_flags.disable_bootstrap_bulk_pull_server = true; + node_flags.disable_bootstrap_listener = true; + node_flags.disable_lazy_bootstrap = true; + node_flags.disable_legacy_bootstrap = true; + node_flags.disable_wallet_bootstrap = true; + nano::node_config node_config (nano::get_available_port (), system.logging); + node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + auto & node1 (*system.add_node (node_config, node_flags)); + nano::genesis genesis; + system.wallet (0)->insert_adhoc (nano::dev_genesis_key.prv); + auto send1 = nano::state_block_builder () + .account (nano::dev_genesis_key.pub) + .previous (genesis.hash ()) + .representative (nano::dev_genesis_key.pub) + .balance (nano::genesis_amount - nano::Gxrb_ratio) + .link (nano::dev_genesis_key.pub) + .sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub) + .work (*node1.work_generate_blocking (genesis.hash ())) + .build_shared (); + auto send1_fork = nano::state_block_builder () + .account (nano::dev_genesis_key.pub) + .previous (genesis.hash ()) + .representative (nano::dev_genesis_key.pub) + .balance (nano::genesis_amount - 2 * nano::Gxrb_ratio) + .link (nano::dev_genesis_key.pub) + .sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub) + .work (*node1.work_generate_blocking (genesis.hash ())) + .build_shared (); + ASSERT_EQ (nano::process_result::progress, node1.process (*send1).code); + // Cache vote + auto vote (std::make_shared (nano::dev_genesis_key.pub, nano::dev_genesis_key.prv, 0, std::vector (1, send1->hash ()))); + node1.vote_processor.vote (vote, std::make_shared (node1)); + node1.history.add (send1->root (), send1->hash (), vote); + auto votes2 (node1.history.votes (send1->root (), send1->hash ())); + ASSERT_EQ (1, votes2.size ()); + ASSERT_EQ (1, votes2[0]->blocks.size ()); + // Start election for forked block + node_config.peering_port = nano::get_available_port (); + auto & node2 (*system.add_node (node_config, node_flags)); + node2.process_active (send1_fork); + node2.block_processor.flush (); + ASSERT_TIMELY (5s, node2.ledger.block_exists (send1->hash ())); +} + TEST (node, vote_republish) { nano::system system (2); diff --git a/nano/node/request_aggregator.cpp b/nano/node/request_aggregator.cpp index 50bbe6a8..2eb0225e 100644 --- a/nano/node/request_aggregator.cpp +++ b/nano/node/request_aggregator.cpp @@ -162,10 +162,10 @@ std::vector> nano::request_aggregator::aggregate (s size_t cached_hashes = 0; std::vector> to_generate; std::vector> cached_votes; - for (auto const & hash_root : requests_a) + for (auto const & [hash, root] : requests_a) { // 1. Votes in cache - auto find_votes (local_votes.votes (hash_root.second, hash_root.first)); + auto find_votes (local_votes.votes (root, hash)); if (!find_votes.empty ()) { ++cached_hashes; @@ -173,26 +173,27 @@ std::vector> nano::request_aggregator::aggregate (s } else { + bool generate_vote (true); // 2. Election winner by hash - auto block = active.winner (hash_root.first); + auto block = active.winner (hash); // 3. Ledger by hash if (block == nullptr) { - block = ledger.store.block_get (transaction, hash_root.first); + block = ledger.store.block_get (transaction, hash); } // 4. Ledger by root - if (block == nullptr && !hash_root.second.is_zero ()) + if (block == nullptr && !root.is_zero ()) { // Search for block root - auto successor (ledger.store.block_successor (transaction, hash_root.second.as_block_hash ())); + auto successor (ledger.store.block_successor (transaction, root.as_block_hash ())); // Search for account root if (successor.is_zero ()) { nano::account_info info; - auto error (ledger.store.account_get (transaction, hash_root.second.as_account (), info)); + auto error (ledger.store.account_get (transaction, root.as_account (), info)); if (!error) { successor = info.open_block; @@ -202,25 +203,27 @@ std::vector> nano::request_aggregator::aggregate (s { auto successor_block = ledger.store.block_get (transaction, successor); debug_assert (successor_block != nullptr); + block = std::move (successor_block); // 5. Votes in cache for successor - auto find_successor_votes (local_votes.votes (hash_root.second, successor)); + auto find_successor_votes (local_votes.votes (root, successor)); if (!find_successor_votes.empty ()) { cached_votes.insert (cached_votes.end (), find_successor_votes.begin (), find_successor_votes.end ()); - } - else - { - block = std::move (successor_block); + generate_vote = false; } } } if (block) { - to_generate.push_back (block); + // Generate new vote + if (generate_vote) + { + to_generate.push_back (block); + } // Let the node know about the alternative block - if (block->hash () != hash_root.first) + if (block->hash () != hash) { nano::publish publish (block); channel_a->send (publish);