aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Towns <aj@erisian.com.au>2021-04-07 11:37:47 +1000
committerAndrew Chow <achow101-github@achow101.com>2021-04-15 20:58:42 -0400
commit71917e01ebf48790b9df48421d8e97986f92e2e4 (patch)
tree15b77a86bc514435fc7b9f245eef3be4641fc527
parent4cab84cfdfc98cd10462681b5eb0fbbc08afd2a7 (diff)
downloadbitcoin-71917e01ebf48790b9df48421d8e97986f92e2e4.tar.xz
tests: test versionbits delayed activation
Github-Pull: #21377 Rebased-From: dd85d5411c1702c8ae259610fe55050ba212e21e
-rw-r--r--src/test/versionbits_tests.cpp83
1 files changed, 74 insertions, 9 deletions
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index ae0d47b2b4..f1b131b498 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -44,6 +44,12 @@ public:
int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, paramsDummy, cache); }
};
+class TestDelayedActivationConditionChecker : public TestConditionChecker
+{
+public:
+ int MinActivationHeight(const Consensus::Params& params) const override { return 15000; }
+};
+
class TestAlwaysActiveConditionChecker : public TestConditionChecker
{
public:
@@ -68,6 +74,8 @@ class VersionBitsTester
// The first one performs all checks, the second only 50%, the third only 25%, etc...
// This is to test whether lack of cached information leads to the same results.
TestConditionChecker checker[CHECKERS];
+ // Another 6 that assume delayed activation
+ TestDelayedActivationConditionChecker checker_delayed[CHECKERS];
// Another 6 that assume always active activation
TestAlwaysActiveConditionChecker checker_always[CHECKERS];
// Another 6 that assume never active activation
@@ -77,14 +85,18 @@ class VersionBitsTester
int num;
public:
- VersionBitsTester() : num(0) {}
+ VersionBitsTester() : num(1000) {}
VersionBitsTester& Reset() {
+ // Have each group of tests be counted by the 1000s part, starting at 1000
+ num = num - (num % 1000) + 1000;
+
for (unsigned int i = 0; i < vpblock.size(); i++) {
delete vpblock[i];
}
for (unsigned int i = 0; i < CHECKERS; i++) {
checker[i] = TestConditionChecker();
+ checker_delayed[i] = TestDelayedActivationConditionChecker();
checker_always[i] = TestAlwaysActiveConditionChecker();
checker_never[i] = TestNeverActiveConditionChecker();
}
@@ -109,11 +121,18 @@ public:
return *this;
}
- VersionBitsTester& TestStateSinceHeight(int height) {
+ VersionBitsTester& TestStateSinceHeight(int height)
+ {
+ return TestStateSinceHeight(height, height);
+ }
+
+ VersionBitsTester& TestStateSinceHeight(int height, int height_delayed)
+ {
const CBlockIndex* tip = Tip();
for (int i = 0; i < CHECKERS; i++) {
if (InsecureRandBits(i) == 0) {
BOOST_CHECK_MESSAGE(checker[i].GetStateSinceHeightFor(tip) == height, strprintf("Test %i for StateSinceHeight", num));
+ BOOST_CHECK_MESSAGE(checker_delayed[i].GetStateSinceHeightFor(tip) == height_delayed, strprintf("Test %i for StateSinceHeight (delayed)", num));
BOOST_CHECK_MESSAGE(checker_always[i].GetStateSinceHeightFor(tip) == 0, strprintf("Test %i for StateSinceHeight (always active)", num));
// never active may go from DEFINED -> FAILED at the first period
@@ -125,17 +144,31 @@ public:
return *this;
}
- VersionBitsTester& TestState(ThresholdState exp) {
+ VersionBitsTester& TestState(ThresholdState exp)
+ {
+ return TestState(exp, exp);
+ }
+
+ VersionBitsTester& TestState(ThresholdState exp, ThresholdState exp_delayed)
+ {
+ if (exp != exp_delayed) {
+ // only expected differences are that delayed stays in locked_in longer
+ BOOST_CHECK_EQUAL(exp, ThresholdState::ACTIVE);
+ BOOST_CHECK_EQUAL(exp_delayed, ThresholdState::LOCKED_IN);
+ }
+
const CBlockIndex* pindex = Tip();
for (int i = 0; i < CHECKERS; i++) {
if (InsecureRandBits(i) == 0) {
ThresholdState got = checker[i].GetStateFor(pindex);
+ ThresholdState got_delayed = checker_delayed[i].GetStateFor(pindex);
ThresholdState got_always = checker_always[i].GetStateFor(pindex);
ThresholdState got_never = checker_never[i].GetStateFor(pindex);
// nHeight of the next block. If vpblock is empty, the next (ie first)
// block should be the genesis block with nHeight == 0.
int height = pindex == nullptr ? 0 : pindex->nHeight + 1;
BOOST_CHECK_MESSAGE(got == exp, strprintf("Test %i for %s height %d (got %s)", num, StateName(exp), height, StateName(got)));
+ BOOST_CHECK_MESSAGE(got_delayed == exp_delayed, strprintf("Test %i for %s height %d (got %s; delayed case)", num, StateName(exp_delayed), height, StateName(got_delayed)));
BOOST_CHECK_MESSAGE(got_always == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE height %d (got %s; always active case)", num, height, StateName(got_always)));
BOOST_CHECK_MESSAGE(got_never == ThresholdState::DEFINED|| got_never == ThresholdState::FAILED, strprintf("Test %i for DEFINED/FAILED height %d (got %s; never active case)", num, height, StateName(got_never)));
}
@@ -150,6 +183,9 @@ public:
VersionBitsTester& TestActive() { return TestState(ThresholdState::ACTIVE); }
VersionBitsTester& TestFailed() { return TestState(ThresholdState::FAILED); }
+ // non-delayed should be active; delayed should still be locked in
+ VersionBitsTester& TestActiveDelayed() { return TestState(ThresholdState::ACTIVE, ThresholdState::LOCKED_IN); }
+
CBlockIndex* Tip() { return vpblock.empty() ? nullptr : vpblock.back(); }
};
@@ -170,7 +206,6 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
.Mine(2001, TestTime(30003), 0x100).TestFailed().TestStateSinceHeight(1000)
.Mine(2999, TestTime(30004), 0x100).TestFailed().TestStateSinceHeight(1000)
.Mine(3000, TestTime(30005), 0x100).TestFailed().TestStateSinceHeight(1000)
-
// DEFINED -> STARTED -> FAILED
.Reset().TestDefined().TestStateSinceHeight(0)
.Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0)
@@ -203,9 +238,10 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
.Mine(2999, TestTime(19999), 0x200).TestStarted().TestStateSinceHeight(2000) // 49 old blocks
.Mine(3000, TestTime(29999), 0x200).TestLockedIn().TestStateSinceHeight(3000) // 1 old block (so 900 out of the past 1000)
.Mine(3999, TestTime(30001), 0).TestLockedIn().TestStateSinceHeight(3000)
- .Mine(4000, TestTime(30002), 0).TestActive().TestStateSinceHeight(4000)
- .Mine(14333, TestTime(30003), 0).TestActive().TestStateSinceHeight(4000)
- .Mine(24000, TestTime(40000), 0).TestActive().TestStateSinceHeight(4000)
+ .Mine(4000, TestTime(30002), 0).TestActiveDelayed().TestStateSinceHeight(4000, 3000) // delayed will not become active until height=15000
+ .Mine(14333, TestTime(30003), 0).TestActiveDelayed().TestStateSinceHeight(4000, 3000)
+ .Mine(15000, TestTime(40000), 0).TestActive().TestStateSinceHeight(4000, 15000)
+ .Mine(24000, TestTime(40000), 0).TestActive().TestStateSinceHeight(4000, 15000)
// DEFINED multiple periods -> STARTED multiple periods -> FAILED
.Reset().TestDefined().TestStateSinceHeight(0)
@@ -216,7 +252,8 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
.Mine(4000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
.Mine(5000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
.Mine(6000, TestTime(20000), 0).TestFailed().TestStateSinceHeight(6000)
- .Mine(7000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(6000);
+ .Mine(7000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(6000)
+ ;
}
}
@@ -230,6 +267,13 @@ BOOST_AUTO_TEST_CASE(versionbits_sanity)
// Make sure that no deployment tries to set an invalid bit.
BOOST_CHECK_EQUAL(bitmask & ~(uint32_t)VERSIONBITS_TOP_MASK, bitmask);
+ // Check min_activation_height is on a retarget boundary
+ BOOST_CHECK_EQUAL(mainnetParams.vDeployments[i].min_activation_height % mainnetParams.nMinerConfirmationWindow, 0U);
+ // Check min_activation_height is 0 for ALWAYS_ACTIVE and never active deployments
+ if (mainnetParams.vDeployments[i].nStartTime == Consensus::BIP9Deployment::ALWAYS_ACTIVE || mainnetParams.vDeployments[i].nTimeout <= 1230768000) {
+ BOOST_CHECK_EQUAL(mainnetParams.vDeployments[i].min_activation_height, 0);
+ }
+
// Verify that the deployment windows of different deployment using the
// same bit are disjoint.
// This test may need modification at such time as a new deployment
@@ -268,7 +312,8 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
BOOST_REQUIRE(nTimeout <= std::numeric_limits<uint32_t>::max() || nTimeout == Consensus::BIP9Deployment::NO_TIMEOUT);
BOOST_REQUIRE(0 <= bit && bit < 32);
BOOST_REQUIRE(((1 << bit) & VERSIONBITS_TOP_MASK) == 0);
- BOOST_REQUIRE(min_activation_height == 0);
+ BOOST_REQUIRE(min_activation_height >= 0);
+ BOOST_REQUIRE_EQUAL(min_activation_height % params.nMinerConfirmationWindow, 0U);
// In the first chain, test that the bit is set by CBV until it has failed.
// In the second chain, test the bit is set by CBV while STARTED and
@@ -378,6 +423,16 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
lastBlock = secondChain.Mine((params.nMinerConfirmationWindow * 3) - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
lastBlock = secondChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+
+ if (lastBlock->nHeight + 1 < min_activation_height) {
+ // check signalling continues while min_activation_height is not reached
+ lastBlock = secondChain.Mine(min_activation_height - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
+ // then reach min_activation_height, which was already REQUIRE'd to start a new period
+ lastBlock = secondChain.Mine(min_activation_height, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ }
+
+ // Check that we don't signal after activation
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
}
@@ -391,6 +446,16 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
check_computeblockversion(chainParams->GetConsensus(), static_cast<Consensus::DeploymentPos>(i));
}
}
+
+ {
+ // Use regtest/testdummy to ensure we always exercise the
+ // min_activation_height test, even if we're not using that in a
+ // live deployment
+ ArgsManager args;
+ args.ForceSetArg("-vbparams", "testdummy:1199145601:1230767999:403200"); // January 1, 2008 - December 31, 2008, min act height 403200
+ const auto chainParams = CreateChainParams(args, CBaseChainParams::REGTEST);
+ check_computeblockversion(chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);
+ }
}
BOOST_AUTO_TEST_SUITE_END()