2018-01-02 18:12:05 +01:00
// Copyright (c) 2014-2017 The Bitcoin Core developers
2016-02-20 02:57:36 +01:00
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-11-10 01:57:53 +01:00
# include <chain.h>
# include <versionbits.h>
# include <test/test_bitcoin.h>
# include <chainparams.h>
# include <validation.h>
# include <consensus/params.h>
2016-02-20 02:57:36 +01:00
# include <boost/test/unit_test.hpp>
/* Define a virtual block time, one block per 10 minutes after Nov 14 2014, 0:55:36am */
int32_t TestTime ( int nHeight ) { return 1415926536 + 600 * nHeight ; }
static const Consensus : : Params paramsDummy = Consensus : : Params ( ) ;
class TestConditionChecker : public AbstractThresholdConditionChecker
{
private :
mutable ThresholdConditionCache cache ;
public :
2017-06-20 21:58:56 +02:00
int64_t BeginTime ( const Consensus : : Params & params ) const override { return TestTime ( 10000 ) ; }
int64_t EndTime ( const Consensus : : Params & params ) const override { return TestTime ( 20000 ) ; }
int Period ( const Consensus : : Params & params ) const override { return 1000 ; }
int Threshold ( const Consensus : : Params & params ) const override { return 900 ; }
bool Condition ( const CBlockIndex * pindex , const Consensus : : Params & params ) const override { return ( pindex - > nVersion & 0x100 ) ; }
2016-02-20 02:57:36 +01:00
ThresholdState GetStateFor ( const CBlockIndex * pindexPrev ) const { return AbstractThresholdConditionChecker : : GetStateFor ( pindexPrev , paramsDummy , cache ) ; }
2016-05-07 00:08:39 +02:00
int GetStateSinceHeightFor ( const CBlockIndex * pindexPrev ) const { return AbstractThresholdConditionChecker : : GetStateSinceHeightFor ( pindexPrev , paramsDummy , cache ) ; }
2016-02-20 02:57:36 +01:00
} ;
2017-10-17 10:24:46 +02:00
class TestAlwaysActiveConditionChecker : public TestConditionChecker
{
public :
int64_t BeginTime ( const Consensus : : Params & params ) const override { return Consensus : : BIP9Deployment : : ALWAYS_ACTIVE ; }
} ;
2016-02-20 02:57:36 +01:00
# define CHECKERS 6
class VersionBitsTester
{
// A fake blockchain
std : : vector < CBlockIndex * > vpblock ;
// 6 independent checkers for the same bit.
// 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 ] ;
2017-10-17 10:24:46 +02:00
// Another 6 that assume always active activation
TestAlwaysActiveConditionChecker checker_always [ CHECKERS ] ;
2016-02-20 02:57:36 +01:00
// Test counter (to identify failures)
int num ;
public :
VersionBitsTester ( ) : num ( 0 ) { }
VersionBitsTester & Reset ( ) {
for ( unsigned int i = 0 ; i < vpblock . size ( ) ; i + + ) {
delete vpblock [ i ] ;
}
for ( unsigned int i = 0 ; i < CHECKERS ; i + + ) {
checker [ i ] = TestConditionChecker ( ) ;
2017-10-17 10:24:46 +02:00
checker_always [ i ] = TestAlwaysActiveConditionChecker ( ) ;
2016-02-20 02:57:36 +01:00
}
vpblock . clear ( ) ;
return * this ;
}
~ VersionBitsTester ( ) {
Reset ( ) ;
}
VersionBitsTester & Mine ( unsigned int height , int32_t nTime , int32_t nVersion ) {
while ( vpblock . size ( ) < height ) {
CBlockIndex * pindex = new CBlockIndex ( ) ;
pindex - > nHeight = vpblock . size ( ) ;
2017-08-07 07:36:37 +02:00
pindex - > pprev = vpblock . size ( ) > 0 ? vpblock . back ( ) : nullptr ;
2016-02-20 02:57:36 +01:00
pindex - > nTime = nTime ;
pindex - > nVersion = nVersion ;
pindex - > BuildSkip ( ) ;
vpblock . push_back ( pindex ) ;
}
return * this ;
}
2016-05-07 00:08:39 +02:00
VersionBitsTester & TestStateSinceHeight ( int height ) {
for ( int i = 0 ; i < CHECKERS ; i + + ) {
2017-06-07 21:03:17 +02:00
if ( InsecureRandBits ( i ) = = 0 ) {
2017-08-07 07:36:37 +02:00
BOOST_CHECK_MESSAGE ( checker [ i ] . GetStateSinceHeightFor ( vpblock . empty ( ) ? nullptr : vpblock . back ( ) ) = = height , strprintf ( " Test %i for StateSinceHeight " , num ) ) ;
2017-10-17 10:24:46 +02:00
BOOST_CHECK_MESSAGE ( checker_always [ i ] . GetStateSinceHeightFor ( vpblock . empty ( ) ? nullptr : vpblock . back ( ) ) = = 0 , strprintf ( " Test %i for StateSinceHeight (always active) " , num ) ) ;
2016-05-07 00:08:39 +02:00
}
}
num + + ;
return * this ;
}
2016-02-20 02:57:36 +01:00
VersionBitsTester & TestDefined ( ) {
for ( int i = 0 ; i < CHECKERS ; i + + ) {
2017-06-07 21:03:17 +02:00
if ( InsecureRandBits ( i ) = = 0 ) {
2018-03-09 15:03:40 +01:00
BOOST_CHECK_MESSAGE ( checker [ i ] . GetStateFor ( vpblock . empty ( ) ? nullptr : vpblock . back ( ) ) = = ThresholdState : : DEFINED , strprintf ( " Test %i for DEFINED " , num ) ) ;
BOOST_CHECK_MESSAGE ( checker_always [ i ] . GetStateFor ( vpblock . empty ( ) ? nullptr : vpblock . back ( ) ) = = ThresholdState : : ACTIVE , strprintf ( " Test %i for ACTIVE (always active) " , num ) ) ;
2016-02-20 02:57:36 +01:00
}
}
num + + ;
return * this ;
}
VersionBitsTester & TestStarted ( ) {
for ( int i = 0 ; i < CHECKERS ; i + + ) {
2017-06-07 21:03:17 +02:00
if ( InsecureRandBits ( i ) = = 0 ) {
2018-03-09 15:03:40 +01:00
BOOST_CHECK_MESSAGE ( checker [ i ] . GetStateFor ( vpblock . empty ( ) ? nullptr : vpblock . back ( ) ) = = ThresholdState : : STARTED , strprintf ( " Test %i for STARTED " , num ) ) ;
BOOST_CHECK_MESSAGE ( checker_always [ i ] . GetStateFor ( vpblock . empty ( ) ? nullptr : vpblock . back ( ) ) = = ThresholdState : : ACTIVE , strprintf ( " Test %i for ACTIVE (always active) " , num ) ) ;
2016-02-20 02:57:36 +01:00
}
}
num + + ;
return * this ;
}
VersionBitsTester & TestLockedIn ( ) {
for ( int i = 0 ; i < CHECKERS ; i + + ) {
2017-06-07 21:03:17 +02:00
if ( InsecureRandBits ( i ) = = 0 ) {
2018-03-09 15:03:40 +01:00
BOOST_CHECK_MESSAGE ( checker [ i ] . GetStateFor ( vpblock . empty ( ) ? nullptr : vpblock . back ( ) ) = = ThresholdState : : LOCKED_IN , strprintf ( " Test %i for LOCKED_IN " , num ) ) ;
BOOST_CHECK_MESSAGE ( checker_always [ i ] . GetStateFor ( vpblock . empty ( ) ? nullptr : vpblock . back ( ) ) = = ThresholdState : : ACTIVE , strprintf ( " Test %i for ACTIVE (always active) " , num ) ) ;
2016-02-20 02:57:36 +01:00
}
}
num + + ;
return * this ;
}
VersionBitsTester & TestActive ( ) {
for ( int i = 0 ; i < CHECKERS ; i + + ) {
2017-06-07 21:03:17 +02:00
if ( InsecureRandBits ( i ) = = 0 ) {
2018-03-09 15:03:40 +01:00
BOOST_CHECK_MESSAGE ( checker [ i ] . GetStateFor ( vpblock . empty ( ) ? nullptr : vpblock . back ( ) ) = = ThresholdState : : ACTIVE , strprintf ( " Test %i for ACTIVE " , num ) ) ;
BOOST_CHECK_MESSAGE ( checker_always [ i ] . GetStateFor ( vpblock . empty ( ) ? nullptr : vpblock . back ( ) ) = = ThresholdState : : ACTIVE , strprintf ( " Test %i for ACTIVE (always active) " , num ) ) ;
2016-02-20 02:57:36 +01:00
}
}
num + + ;
return * this ;
}
VersionBitsTester & TestFailed ( ) {
for ( int i = 0 ; i < CHECKERS ; i + + ) {
2017-06-07 21:03:17 +02:00
if ( InsecureRandBits ( i ) = = 0 ) {
2018-03-09 15:03:40 +01:00
BOOST_CHECK_MESSAGE ( checker [ i ] . GetStateFor ( vpblock . empty ( ) ? nullptr : vpblock . back ( ) ) = = ThresholdState : : FAILED , strprintf ( " Test %i for FAILED " , num ) ) ;
BOOST_CHECK_MESSAGE ( checker_always [ i ] . GetStateFor ( vpblock . empty ( ) ? nullptr : vpblock . back ( ) ) = = ThresholdState : : ACTIVE , strprintf ( " Test %i for ACTIVE (always active) " , num ) ) ;
2016-02-20 02:57:36 +01:00
}
}
num + + ;
return * this ;
}
2016-03-09 22:00:53 +01:00
2017-08-07 07:36:37 +02:00
CBlockIndex * Tip ( ) { return vpblock . size ( ) ? vpblock . back ( ) : nullptr ; }
2016-02-20 02:57:36 +01:00
} ;
BOOST_FIXTURE_TEST_SUITE ( versionbits_tests , TestingSetup )
BOOST_AUTO_TEST_CASE ( versionbits_test )
{
for ( int i = 0 ; i < 64 ; i + + ) {
// DEFINED -> FAILED
2016-05-07 00:08:39 +02:00
VersionBitsTester ( ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 1 , TestTime ( 1 ) , 0x100 ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 11 , TestTime ( 11 ) , 0x100 ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 989 , TestTime ( 989 ) , 0x100 ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 999 , TestTime ( 20000 ) , 0x100 ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 1000 , TestTime ( 20000 ) , 0x100 ) . TestFailed ( ) . TestStateSinceHeight ( 1000 )
. Mine ( 1999 , TestTime ( 30001 ) , 0x100 ) . TestFailed ( ) . TestStateSinceHeight ( 1000 )
. Mine ( 2000 , TestTime ( 30002 ) , 0x100 ) . TestFailed ( ) . TestStateSinceHeight ( 1000 )
. Mine ( 2001 , TestTime ( 30003 ) , 0x100 ) . TestFailed ( ) . TestStateSinceHeight ( 1000 )
. Mine ( 2999 , TestTime ( 30004 ) , 0x100 ) . TestFailed ( ) . TestStateSinceHeight ( 1000 )
. Mine ( 3000 , TestTime ( 30005 ) , 0x100 ) . TestFailed ( ) . TestStateSinceHeight ( 1000 )
2016-02-20 02:57:36 +01:00
// DEFINED -> STARTED -> FAILED
2016-05-07 00:08:39 +02:00
. Reset ( ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 1 , TestTime ( 1 ) , 0 ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 1000 , TestTime ( 10000 ) - 1 , 0x100 ) . TestDefined ( ) . TestStateSinceHeight ( 0 ) // One second more and it would be defined
. Mine ( 2000 , TestTime ( 10000 ) , 0x100 ) . TestStarted ( ) . TestStateSinceHeight ( 2000 ) // So that's what happens the next period
. Mine ( 2051 , TestTime ( 10010 ) , 0 ) . TestStarted ( ) . TestStateSinceHeight ( 2000 ) // 51 old blocks
. Mine ( 2950 , TestTime ( 10020 ) , 0x100 ) . TestStarted ( ) . TestStateSinceHeight ( 2000 ) // 899 new blocks
. Mine ( 3000 , TestTime ( 20000 ) , 0 ) . TestFailed ( ) . TestStateSinceHeight ( 3000 ) // 50 old blocks (so 899 out of the past 1000)
. Mine ( 4000 , TestTime ( 20010 ) , 0x100 ) . TestFailed ( ) . TestStateSinceHeight ( 3000 )
2016-02-20 02:57:36 +01:00
// DEFINED -> STARTED -> FAILED while threshold reached
2016-05-07 00:08:39 +02:00
. Reset ( ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 1 , TestTime ( 1 ) , 0 ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 1000 , TestTime ( 10000 ) - 1 , 0x101 ) . TestDefined ( ) . TestStateSinceHeight ( 0 ) // One second more and it would be defined
. Mine ( 2000 , TestTime ( 10000 ) , 0x101 ) . TestStarted ( ) . TestStateSinceHeight ( 2000 ) // So that's what happens the next period
. Mine ( 2999 , TestTime ( 30000 ) , 0x100 ) . TestStarted ( ) . TestStateSinceHeight ( 2000 ) // 999 new blocks
. Mine ( 3000 , TestTime ( 30000 ) , 0x100 ) . TestFailed ( ) . TestStateSinceHeight ( 3000 ) // 1 new block (so 1000 out of the past 1000 are new)
. Mine ( 3999 , TestTime ( 30001 ) , 0 ) . TestFailed ( ) . TestStateSinceHeight ( 3000 )
. Mine ( 4000 , TestTime ( 30002 ) , 0 ) . TestFailed ( ) . TestStateSinceHeight ( 3000 )
. Mine ( 14333 , TestTime ( 30003 ) , 0 ) . TestFailed ( ) . TestStateSinceHeight ( 3000 )
. Mine ( 24000 , TestTime ( 40000 ) , 0 ) . TestFailed ( ) . TestStateSinceHeight ( 3000 )
2016-02-20 02:57:36 +01:00
// DEFINED -> STARTED -> LOCKEDIN at the last minute -> ACTIVE
. Reset ( ) . TestDefined ( )
2016-05-07 00:08:39 +02:00
. Mine ( 1 , TestTime ( 1 ) , 0 ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 1000 , TestTime ( 10000 ) - 1 , 0x101 ) . TestDefined ( ) . TestStateSinceHeight ( 0 ) // One second more and it would be defined
. Mine ( 2000 , TestTime ( 10000 ) , 0x101 ) . TestStarted ( ) . TestStateSinceHeight ( 2000 ) // So that's what happens the next period
. Mine ( 2050 , TestTime ( 10010 ) , 0x200 ) . TestStarted ( ) . TestStateSinceHeight ( 2000 ) // 50 old blocks
. Mine ( 2950 , TestTime ( 10020 ) , 0x100 ) . TestStarted ( ) . TestStateSinceHeight ( 2000 ) // 900 new blocks
. 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 )
// DEFINED multiple periods -> STARTED multiple periods -> FAILED
. Reset ( ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 999 , TestTime ( 999 ) , 0 ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 1000 , TestTime ( 1000 ) , 0 ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 2000 , TestTime ( 2000 ) , 0 ) . TestDefined ( ) . TestStateSinceHeight ( 0 )
. Mine ( 3000 , TestTime ( 10000 ) , 0 ) . TestStarted ( ) . TestStateSinceHeight ( 3000 )
. 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 ) ;
2016-02-20 02:57:36 +01:00
}
2016-03-09 15:48:20 +01:00
// Sanity checks of version bit deployments
2015-11-28 15:04:35 +01:00
const auto chainParams = CreateChainParams ( CBaseChainParams : : MAIN ) ;
const Consensus : : Params & mainnetParams = chainParams - > GetConsensus ( ) ;
2016-03-09 15:48:20 +01:00
for ( int i = 0 ; i < ( int ) Consensus : : MAX_VERSION_BITS_DEPLOYMENTS ; i + + ) {
2017-06-01 16:13:35 +02:00
uint32_t bitmask = VersionBitsMask ( mainnetParams , static_cast < Consensus : : DeploymentPos > ( i ) ) ;
2016-03-09 15:48:20 +01:00
// Make sure that no deployment tries to set an invalid bit.
BOOST_CHECK_EQUAL ( bitmask & ~ ( uint32_t ) VERSIONBITS_TOP_MASK , bitmask ) ;
// 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
// is proposed that reuses the bit of an activated soft fork, before the
// end time of that soft fork. (Alternatively, the end time of that
// activated soft fork could be later changed to be earlier to avoid
// overlap.)
for ( int j = i + 1 ; j < ( int ) Consensus : : MAX_VERSION_BITS_DEPLOYMENTS ; j + + ) {
2017-06-01 16:13:35 +02:00
if ( VersionBitsMask ( mainnetParams , static_cast < Consensus : : DeploymentPos > ( j ) ) = = bitmask ) {
2016-03-09 15:48:20 +01:00
BOOST_CHECK ( mainnetParams . vDeployments [ j ] . nStartTime > mainnetParams . vDeployments [ i ] . nTimeout | |
mainnetParams . vDeployments [ i ] . nStartTime > mainnetParams . vDeployments [ j ] . nTimeout ) ;
}
}
}
2016-02-20 02:57:36 +01:00
}
2016-03-09 22:00:53 +01:00
BOOST_AUTO_TEST_CASE ( versionbits_computeblockversion )
{
// Check that ComputeBlockVersion will set the appropriate bit correctly
// on mainnet.
2015-11-28 15:04:35 +01:00
const auto chainParams = CreateChainParams ( CBaseChainParams : : MAIN ) ;
const Consensus : : Params & mainnetParams = chainParams - > GetConsensus ( ) ;
2016-03-09 22:00:53 +01:00
// Use the TESTDUMMY deployment for testing purposes.
int64_t bit = mainnetParams . vDeployments [ Consensus : : DEPLOYMENT_TESTDUMMY ] . bit ;
int64_t nStartTime = mainnetParams . vDeployments [ Consensus : : DEPLOYMENT_TESTDUMMY ] . nStartTime ;
int64_t nTimeout = mainnetParams . vDeployments [ Consensus : : DEPLOYMENT_TESTDUMMY ] . nTimeout ;
assert ( nStartTime < nTimeout ) ;
// 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
// LOCKED-IN, and then no longer set while ACTIVE.
VersionBitsTester firstChain , secondChain ;
// Start generating blocks before nStartTime
int64_t nTime = nStartTime - 1 ;
// Before MedianTimePast of the chain has crossed nStartTime, the bit
// should not be set.
2017-08-07 07:36:37 +02:00
CBlockIndex * lastBlock = nullptr ;
2016-03-09 22:00:53 +01:00
lastBlock = firstChain . Mine ( 2016 , nTime , VERSIONBITS_LAST_OLD_BLOCK_VERSION ) . Tip ( ) ;
BOOST_CHECK_EQUAL ( ComputeBlockVersion ( lastBlock , mainnetParams ) & ( 1 < < bit ) , 0 ) ;
// Mine 2011 more blocks at the old time, and check that CBV isn't setting the bit yet.
for ( int i = 1 ; i < 2012 ; i + + ) {
lastBlock = firstChain . Mine ( 2016 + i , nTime , VERSIONBITS_LAST_OLD_BLOCK_VERSION ) . Tip ( ) ;
// This works because VERSIONBITS_LAST_OLD_BLOCK_VERSION happens
// to be 4, and the bit we're testing happens to be bit 28.
BOOST_CHECK_EQUAL ( ComputeBlockVersion ( lastBlock , mainnetParams ) & ( 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 ( int i = 2012 ; i < = 2016 ; i + + ) {
lastBlock = firstChain . Mine ( 2016 + i , nTime , VERSIONBITS_LAST_OLD_BLOCK_VERSION ) . Tip ( ) ;
BOOST_CHECK_EQUAL ( ComputeBlockVersion ( lastBlock , mainnetParams ) & ( 1 < < bit ) , 0 ) ;
}
// Advance to the next period and transition to STARTED,
lastBlock = firstChain . Mine ( 6048 , nTime , VERSIONBITS_LAST_OLD_BLOCK_VERSION ) . Tip ( ) ;
// so ComputeBlockVersion should now set the bit,
BOOST_CHECK ( ( ComputeBlockVersion ( lastBlock , mainnetParams ) & ( 1 < < bit ) ) ! = 0 ) ;
// and should also be using the VERSIONBITS_TOP_BITS.
BOOST_CHECK_EQUAL ( ComputeBlockVersion ( lastBlock , mainnetParams ) & VERSIONBITS_TOP_MASK , VERSIONBITS_TOP_BITS ) ;
// Check that ComputeBlockVersion will set the bit until nTimeout
nTime + = 600 ;
int blocksToMine = 4032 ; // test blocks for up to 2 time periods
int nHeight = 6048 ;
// 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 ( ) ;
BOOST_CHECK ( ( ComputeBlockVersion ( lastBlock , mainnetParams ) & ( 1 < < bit ) ) ! = 0 ) ;
BOOST_CHECK_EQUAL ( ComputeBlockVersion ( lastBlock , mainnetParams ) & VERSIONBITS_TOP_MASK , VERSIONBITS_TOP_BITS ) ;
blocksToMine - - ;
nTime + = 600 ;
nHeight + = 1 ;
2017-01-14 21:45:32 +01:00
}
2016-03-09 22:00:53 +01:00
nTime = nTimeout ;
// FAILED is only triggered at the end of a period, so CBV should be setting
// the bit until the period transition.
for ( int i = 0 ; i < 2015 ; i + + ) {
lastBlock = firstChain . Mine ( nHeight + 1 , nTime , VERSIONBITS_LAST_OLD_BLOCK_VERSION ) . Tip ( ) ;
BOOST_CHECK ( ( ComputeBlockVersion ( lastBlock , mainnetParams ) & ( 1 < < bit ) ) ! = 0 ) ;
nHeight + = 1 ;
}
// The next block should trigger no longer setting the bit.
lastBlock = firstChain . Mine ( nHeight + 1 , nTime , VERSIONBITS_LAST_OLD_BLOCK_VERSION ) . Tip ( ) ;
BOOST_CHECK_EQUAL ( ComputeBlockVersion ( lastBlock , mainnetParams ) & ( 1 < < bit ) , 0 ) ;
// On a new chain:
// verify that the bit will be set after lock-in, and then stop being set
// after activation.
nTime = nStartTime ;
// Mine one period worth of blocks, and check that the bit will be on for the
// next period.
2017-08-26 14:12:00 +02:00
lastBlock = secondChain . Mine ( 2016 , nTime , VERSIONBITS_LAST_OLD_BLOCK_VERSION ) . Tip ( ) ;
2016-03-09 22:00:53 +01:00
BOOST_CHECK ( ( ComputeBlockVersion ( lastBlock , mainnetParams ) & ( 1 < < bit ) ) ! = 0 ) ;
// Mine another period worth of blocks, signaling the new bit.
2017-08-26 14:12:00 +02:00
lastBlock = secondChain . Mine ( 4032 , nTime , VERSIONBITS_TOP_BITS | ( 1 < < bit ) ) . Tip ( ) ;
2016-03-09 22:00:53 +01:00
// 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 ( ( ComputeBlockVersion ( lastBlock , mainnetParams ) & ( 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.
2017-08-26 14:12:00 +02:00
lastBlock = secondChain . Mine ( 6047 , nTime , VERSIONBITS_LAST_OLD_BLOCK_VERSION ) . Tip ( ) ;
2016-03-09 22:00:53 +01:00
BOOST_CHECK ( ( ComputeBlockVersion ( lastBlock , mainnetParams ) & ( 1 < < bit ) ) ! = 0 ) ;
2017-08-26 14:12:00 +02:00
lastBlock = secondChain . Mine ( 6048 , nTime , VERSIONBITS_LAST_OLD_BLOCK_VERSION ) . Tip ( ) ;
2016-03-09 22:00:53 +01:00
BOOST_CHECK_EQUAL ( ComputeBlockVersion ( lastBlock , mainnetParams ) & ( 1 < < bit ) , 0 ) ;
// Finally, verify that after a soft fork has activated, CBV no longer uses
// VERSIONBITS_LAST_OLD_BLOCK_VERSION.
//BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
}
2016-02-20 02:57:36 +01:00
BOOST_AUTO_TEST_SUITE_END ( )