miner: have waitNext return after 20 min on testnet

On testnet we need to create a min diff template after 20 min.
This commit is contained in:
Sjors Provoost 2025-01-31 17:19:28 +01:00
parent d4020f502a
commit cadbd4137d
No known key found for this signature in database
GPG Key ID: 57FF9BDBCC301009
5 changed files with 94 additions and 0 deletions

View File

@ -64,6 +64,9 @@ public:
* for the next block should rise (default infinite).
*
* @returns a new BlockTemplate or nothing if the timeout occurs.
*
* On testnet this will additionally return a template with difficulty 1 if
* the tip is more than 20 minutes old.
*/
virtual std::unique_ptr<BlockTemplate> waitNext(const node::BlockWaitOptions options = {}) = 0;
};

View File

@ -958,6 +958,7 @@ public:
auto now{NodeClock::now()};
const auto deadline = now + options.timeout;
const MillisecondsDouble tick{1000};
const bool allow_min_difficulty{chainman().GetParams().GetConsensus().fPowAllowMinDifficultyBlocks};
do {
bool tip_changed{false};
@ -982,6 +983,14 @@ public:
// Must release m_tip_block_mutex before locking cs_main, to avoid deadlocks.
LOCK(::cs_main);
// On test networks return a minimum difficulty block after 20 minutes
if (!tip_changed && allow_min_difficulty) {
const NodeClock::time_point tip_time{std::chrono::seconds{chainman().ActiveChain().Tip()->GetBlockTime()}};
if (now > tip_time + 20min) {
tip_changed = true;
}
}
/**
* We determine if fees increased compared to the previous template by generating
* a fresh template. There may be more efficient ways to determine how much

View File

@ -121,6 +121,7 @@ add_executable(test_bitcoin
streams_tests.cpp
sync_tests.cpp
system_tests.cpp
testnet4_miner_tests.cpp
timeoffsets_tests.cpp
torcontrol_tests.cpp
transaction_tests.cpp

View File

@ -0,0 +1,75 @@
// Copyright (c) 2025 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <common/system.h>
#include <interfaces/mining.h>
#include <node/miner.h>
#include <util/time.h>
#include <validation.h>
#include <test/util/setup_common.h>
#include <boost/test/unit_test.hpp>
using interfaces::BlockTemplate;
using interfaces::Mining;
using node::BlockAssembler;
using node::BlockWaitOptions;
namespace testnet4_miner_tests {
struct Testnet4MinerTestingSetup : public Testnet4Setup {
std::unique_ptr<Mining> MakeMining()
{
return interfaces::MakeMining(m_node);
}
};
} // namespace testnet4_miner_tests
BOOST_FIXTURE_TEST_SUITE(testnet4_miner_tests, Testnet4MinerTestingSetup)
BOOST_AUTO_TEST_CASE(MiningInterface)
{
auto mining{MakeMining()};
BOOST_REQUIRE(mining);
BlockAssembler::Options options;
std::unique_ptr<BlockTemplate> block_template;
// Set node time a few minutes past the testnet4 genesis block
const int64_t genesis_time{WITH_LOCK(cs_main, return m_node.chainman->ActiveChain().Tip()->GetBlockTime())};
SetMockTime(genesis_time + 3 * 60);
block_template = mining->createNewBlock(options);
BOOST_REQUIRE(block_template);
// The template should use the mocked system time
BOOST_REQUIRE_EQUAL(block_template->getBlockHeader().nTime, genesis_time + 3 * 60);
const BlockWaitOptions wait_options{.timeout = MillisecondsDouble{0}, .fee_threshold = 1};
// waitNext() should return nullptr because there is no better template
auto should_be_nullptr = block_template->waitNext(wait_options);
BOOST_REQUIRE(should_be_nullptr == nullptr);
// This remains the case when exactly 20 minutes have gone by
{
LOCK(cs_main);
SetMockTime(m_node.chainman->ActiveChain().Tip()->GetBlockTime() + 20 * 60);
}
should_be_nullptr = block_template->waitNext(wait_options);
BOOST_REQUIRE(should_be_nullptr == nullptr);
// One second later the difficulty drops and it returns a new template
// Note that we can't test the actual difficulty change, because the
// difficulty is already at 1.
{
LOCK(cs_main);
SetMockTime(m_node.chainman->ActiveChain().Tip()->GetBlockTime() + 20 * 60 + 1);
}
block_template = block_template->waitNext(wait_options);
BOOST_REQUIRE(block_template);
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -130,6 +130,12 @@ struct RegTestingSetup : public TestingSetup {
: TestingSetup{ChainType::REGTEST} {}
};
/** Identical to TestingSetup, but chain set to testnet4 */
struct Testnet4Setup : public TestingSetup {
Testnet4Setup()
: TestingSetup{ChainType::TESTNET4} {}
};
class CBlock;
struct CMutableTransaction;
class CScript;