From 4a9dd03485754d97a89e7772df99689418b2e315 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 31 Oct 2023 10:30:10 -0500 Subject: [PATCH] GH-1837 Do not start a speculative block that will immediately be restarted --- plugins/producer_plugin/producer_plugin.cpp | 11 +++++++++-- .../producer_plugin/test/test_block_timing_util.cpp | 7 +++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 4d4c7d4741..e5fcf20dd2 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -1829,8 +1829,6 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() { last_start_block_time = now; } - // create speculative blocks at regular intervals, so we create blocks with "current" block time - _pending_block_deadline = block_timing_util::calculate_producing_block_deadline(_produce_block_cpu_effort, block_time); if (in_producing_mode()) { uint32_t production_round_index = block_timestamp_type(block_time).slot % chain::config::producer_repetitions; if (production_round_index == 0) { @@ -1844,6 +1842,15 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() { } } + // create speculative blocks at regular intervals, so we create blocks with "current" block time + _pending_block_deadline = block_timing_util::calculate_producing_block_deadline(_produce_block_cpu_effort, block_time); + if (in_speculating_mode()) { // if we are producing, then produce block even if deadline has pasted + // speculative block, no reason to start a block that will immediately be re-started, set deadline in the future + // a block should come in during this time, if not then just keep creating the block every produce_block_cpu_effort + if (now + fc::milliseconds(config::block_interval_ms/10) > _pending_block_deadline) { + _pending_block_deadline = now + _produce_block_cpu_effort; + } + } const auto& preprocess_deadline = _pending_block_deadline; fc_dlog(_log, "Starting block #${n} at ${time} producer ${p}", ("n", pending_block_num)("time", now)("p", scheduled_producer.producer_name)); diff --git a/plugins/producer_plugin/test/test_block_timing_util.cpp b/plugins/producer_plugin/test/test_block_timing_util.cpp index 066cc505b3..8943a6ea3f 100644 --- a/plugins/producer_plugin/test/test_block_timing_util.cpp +++ b/plugins/producer_plugin/test/test_block_timing_util.cpp @@ -114,6 +114,13 @@ BOOST_AUTO_TEST_CASE(test_calculate_block_deadline) { // 29.962500 + (450000/12) = 30.425 BOOST_CHECK_EQUAL(block_deadline, fc::time_point::from_iso_string("2023-10-29T13:40:30.425")); } + { + // Real scenario that caused multiple start blocks + auto default_cpu_effort = fc::microseconds(block_interval.count() - (450000/12)); // 462,500 + auto block_time = eosio::chain::block_timestamp_type(fc::time_point::from_iso_string("2023-10-31T13:37:35.000")); + fc::time_point block_deadline = calculate_producing_block_deadline(default_cpu_effort, block_time); + BOOST_CHECK_EQUAL(block_deadline.to_iso_string(), fc::time_point::from_iso_string("2023-10-31T13:37:34.587").to_iso_string()); + } } BOOST_AUTO_TEST_CASE(test_calculate_producer_wake_up_time) {