diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index 09ba6cae49..a856da1e79 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -727,6 +727,71 @@ TEST (active_transactions, dropped_cleanup) ASSERT_EQ (0, node.active.blocks.count (block->hash ())); } +TEST (active_transactions, republish_winner) +{ + nano::system system; + 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_config.peering_port = nano::get_available_port (); + auto & node2 (*system.add_node (node_config)); + + nano::genesis genesis; + nano::keypair key; + nano::state_block_builder builder; + auto send1 = builder.make_block () + .account (nano::dev_genesis_key.pub) + .previous (genesis.hash ()) + .representative (nano::dev_genesis_key.pub) + .balance (nano::genesis_amount - nano::Gxrb_ratio) + .link (key.pub) + .sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub) + .work (*system.work.generate (genesis.hash ())) + .build_shared (); + + node1.process_active (send1); + node1.block_processor.flush (); + ASSERT_TIMELY (3s, node2.stats.count (nano::stat::type::message, nano::stat::detail::publish, nano::stat::dir::in) == 1); + + // Several forks + for (auto i (0); i < 5; i++) + { + auto fork = builder.make_block () + .account (nano::dev_genesis_key.pub) + .previous (genesis.hash ()) + .representative (nano::dev_genesis_key.pub) + .balance (nano::genesis_amount - 1 - i) + .link (key.pub) + .sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub) + .work (*system.work.generate (genesis.hash ())) + .build_shared (); + node1.process_active (fork); + } + node1.block_processor.flush (); + ASSERT_TIMELY (3s, !node1.active.empty ()); + ASSERT_EQ (1, node2.stats.count (nano::stat::type::message, nano::stat::detail::publish, nano::stat::dir::in)); + + // Process new fork with vote to change winner + auto fork = builder.make_block () + .account (nano::dev_genesis_key.pub) + .previous (genesis.hash ()) + .representative (nano::dev_genesis_key.pub) + .balance (nano::genesis_amount - 2 * nano::Gxrb_ratio) + .link (key.pub) + .sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub) + .work (*system.work.generate (genesis.hash ())) + .build_shared (); + + node1.process_active (fork); + node1.block_processor.flush (); + auto vote (std::make_shared (nano::dev_genesis_key.pub, nano::dev_genesis_key.prv, 0, std::vector{ fork->hash () })); + node1.vote_processor.vote (vote, std::make_shared (node1)); + node1.vote_processor.flush (); + node1.block_processor.flush (); + + ASSERT_TIMELY (3s, node2.stats.count (nano::stat::type::message, nano::stat::detail::publish, nano::stat::dir::in) == 2); +} + TEST (active_transactions, fork_filter_cleanup) { nano::system system; diff --git a/nano/node/active_transactions.cpp b/nano/node/active_transactions.cpp index 7728931941..d0d0769608 100644 --- a/nano/node/active_transactions.cpp +++ b/nano/node/active_transactions.cpp @@ -1269,7 +1269,6 @@ bool nano::active_transactions::publish (std::shared_ptr block_a) auto const cache = find_inactive_votes_cache_impl (block_a->hash ()); lock.unlock (); election->insert_inactive_votes_cache (cache); - node.network.flood_block (block_a, nano::buffer_drop_policy::no_limiter_drop); node.stats.inc (nano::stat::type::election, nano::stat::detail::election_block_conflict); } } diff --git a/nano/node/blockprocessor.cpp b/nano/node/blockprocessor.cpp index fc7440dc63..069bcf24e4 100644 --- a/nano/node/blockprocessor.cpp +++ b/nano/node/blockprocessor.cpp @@ -316,7 +316,7 @@ void nano::block_processor::process_batch (nano::unique_lock & lock_ } } number_of_blocks_processed++; - process_one (transaction, post_events, info); + process_one (transaction, post_events, info, false, force); } lock_a.lock (); } @@ -363,7 +363,7 @@ void nano::block_processor::process_live (nano::transaction const & transaction_ } } -nano::process_return nano::block_processor::process_one (nano::write_transaction const & transaction_a, block_post_events & events_a, nano::unchecked_info info_a, const bool watch_work_a, nano::block_origin const origin_a) +nano::process_return nano::block_processor::process_one (nano::write_transaction const & transaction_a, block_post_events & events_a, nano::unchecked_info info_a, const bool watch_work_a, const bool forced_a, nano::block_origin const origin_a) { nano::process_return result; auto block (info_a.block); @@ -380,7 +380,7 @@ nano::process_return nano::block_processor::process_one (nano::write_transaction block->serialize_json (block_string, node.config.logging.single_line_record ()); node.logger.try_log (boost::str (boost::format ("Processing block %1%: %2%") % hash.to_string () % block_string)); } - if (info_a.modified > nano::seconds_since_epoch () - 300 && node.block_arrival.recent (hash)) + if ((info_a.modified > nano::seconds_since_epoch () - 300 && node.block_arrival.recent (hash)) || forced_a) { events_a.events.emplace_back ([this, hash, block = info_a.block, result, watch_work_a, origin_a](nano::transaction const & post_event_transaction_a) { process_live (post_event_transaction_a, hash, block, result, watch_work_a, origin_a); }); } diff --git a/nano/node/blockprocessor.hpp b/nano/node/blockprocessor.hpp index 1956e6fb50..b41efdf460 100644 --- a/nano/node/blockprocessor.hpp +++ b/nano/node/blockprocessor.hpp @@ -62,7 +62,7 @@ class block_processor final bool have_blocks_ready (); bool have_blocks (); void process_blocks (); - nano::process_return process_one (nano::write_transaction const &, block_post_events &, nano::unchecked_info, const bool = false, nano::block_origin const = nano::block_origin::remote); + nano::process_return process_one (nano::write_transaction const &, block_post_events &, nano::unchecked_info, const bool = false, const bool = false, nano::block_origin const = nano::block_origin::remote); nano::process_return process_one (nano::write_transaction const &, block_post_events &, std::shared_ptr const &, const bool = false); std::atomic flushing{ false }; // Delay required for average network propagartion before requesting confirmation diff --git a/nano/node/node.cpp b/nano/node/node.cpp index 7d036fcb77..6b0c9f9447 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -632,7 +632,7 @@ nano::process_return nano::node::process_local (std::shared_ptr con // Process block block_post_events post_events ([& store = store] { return store.tx_begin_read (); }); auto transaction (store.tx_begin_write ({ tables::accounts, tables::blocks, tables::frontiers, tables::pending }, { tables::confirmation_height })); - return block_processor.process_one (transaction, post_events, info, work_watcher_a, nano::block_origin::local); + return block_processor.process_one (transaction, post_events, info, work_watcher_a, false, nano::block_origin::local); } void nano::node::start ()