consensus/params: Move version bits period/threshold to bip9 param

Rather than having the rule change period/threshold be constant for all
potential deployments on a chain, have it be specific to the deployment
itself. This both matches history (BIP 9 specified a 2016 block period
and 1916 block threshold; BIP 91 specified a 336 block period and 269
block threshold; and BIP 341 specified a 2016 block period and 1815
block threshold), and allows the code to be simplified, as only the
BIP9Deployment structure is needed, not the full Consensus::Params
structure.
This commit is contained in:
Anthony Towns
2023-12-07 12:16:22 +10:00
parent e9d617095d
commit a679040ec1
5 changed files with 76 additions and 45 deletions

View File

@@ -268,6 +268,12 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens
int64_t nStartTime = params.vDeployments[dep].nStartTime;
int64_t nTimeout = params.vDeployments[dep].nTimeout;
int min_activation_height = params.vDeployments[dep].min_activation_height;
uint32_t period = params.vDeployments[dep].period;
uint32_t threshold = params.vDeployments[dep].threshold;
BOOST_REQUIRE(period > 0); // no division by zero, thankyou
BOOST_REQUIRE(0 < threshold); // must be able to have a window that doesn't activate
BOOST_REQUIRE(threshold < period); // must be able to have a window that does activate
// should not be any signalling for first block
BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(nullptr, params), VERSIONBITS_TOP_BITS);
@@ -289,7 +295,7 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens
BOOST_REQUIRE(((1 << bit) & VERSIONBITS_TOP_MASK) == 0);
BOOST_REQUIRE(min_activation_height >= 0);
// Check min_activation_height is on a retarget boundary
BOOST_REQUIRE_EQUAL(min_activation_height % params.nMinerConfirmationWindow, 0U);
BOOST_REQUIRE_EQUAL(min_activation_height % period, 0U);
const uint32_t bitmask{versionbitscache.Mask(params, dep)};
BOOST_CHECK_EQUAL(bitmask, uint32_t{1} << bit);
@@ -309,9 +315,9 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens
// since CBlockIndex::nTime is uint32_t we can't represent any
// earlier time, so will transition from DEFINED to STARTED at the
// end of the first period by mining blocks at nTime == 0
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
lastBlock = firstChain.Mine(period - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
lastBlock = firstChain.Mine(period, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
// then we'll keep mining at nStartTime...
} else {
@@ -319,25 +325,25 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens
--nTime;
// Start generating blocks before nStartTime
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
lastBlock = firstChain.Mine(period, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
// Mine more blocks (4 less than the adjustment period) at the old time, and check that CBV isn't setting the bit yet.
for (uint32_t i = 1; i < params.nMinerConfirmationWindow - 4; i++) {
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
for (uint32_t i = 1; i < period - 4; i++) {
lastBlock = firstChain.Mine(period + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
}
// Now mine 5 more blocks at the start time -- MTP should not have passed yet, so
// CBV should still not yet set the bit.
nTime = nStartTime;
for (uint32_t i = params.nMinerConfirmationWindow - 4; i <= params.nMinerConfirmationWindow; i++) {
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
for (uint32_t i = period - 4; i <= period; i++) {
lastBlock = firstChain.Mine(period + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
}
// Next we will advance to the next period and transition to STARTED,
}
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
lastBlock = firstChain.Mine(period * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
// so ComputeBlockVersion should now set the bit,
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
// and should also be using the VERSIONBITS_TOP_BITS.
@@ -345,8 +351,8 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens
// Check that ComputeBlockVersion will set the bit until nTimeout
nTime += 600;
uint32_t blocksToMine = params.nMinerConfirmationWindow * 2; // test blocks for up to 2 time periods
uint32_t nHeight = params.nMinerConfirmationWindow * 3;
uint32_t blocksToMine = period * 2; // test blocks for up to 2 time periods
uint32_t nHeight = period * 3;
// These blocks are all before nTimeout is reached.
while (nTime < nTimeout && blocksToMine > 0) {
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
@@ -363,7 +369,7 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens
nTime = nTimeout;
// finish the last period before we start timing out
while (nHeight % params.nMinerConfirmationWindow != 0) {
while (nHeight % period != 0) {
lastBlock = firstChain.Mine(nHeight+1, nTime - 1, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
nHeight += 1;
@@ -371,7 +377,7 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens
// FAILED is only triggered at the end of a period, so CBV should be setting
// the bit until the period transition.
for (uint32_t i = 0; i < params.nMinerConfirmationWindow - 1; i++) {
for (uint32_t i = 0; i < period - 1; i++) {
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
nHeight += 1;
@@ -388,20 +394,20 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens
// Mine one period worth of blocks, and check that the bit will be on for the
// next period.
lastBlock = secondChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
lastBlock = secondChain.Mine(period, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
// Mine another period worth of blocks, signaling the new bit.
lastBlock = secondChain.Mine(params.nMinerConfirmationWindow * 2, nTime, VERSIONBITS_TOP_BITS | (1<<bit)).Tip();
lastBlock = secondChain.Mine(period * 2, nTime, VERSIONBITS_TOP_BITS | (1<<bit)).Tip();
// After one period of setting the bit on each block, it should have locked in.
// We keep setting the bit for one more period though, until activation.
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
// Now check that we keep mining the block until the end of this period, and
// then stop at the beginning of the next period.
lastBlock = secondChain.Mine((params.nMinerConfirmationWindow * 3) - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
lastBlock = secondChain.Mine((period * 3) - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
lastBlock = secondChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
lastBlock = secondChain.Mine(period * 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