@@ -19,6 +19,7 @@ static const std::string StateName(ThresholdState state)
1919 switch (state) {
2020 case ThresholdState::DEFINED: return " DEFINED" ;
2121 case ThresholdState::STARTED: return " STARTED" ;
22+ case ThresholdState::LAST_CHANCE: return " LAST_CHANCE" ;
2223 case ThresholdState::DELAYED: return " DELAYED" ;
2324 case ThresholdState::LOCKED_IN: return " LOCKED_IN" ;
2425 case ThresholdState::ACTIVE: return " ACTIVE" ;
@@ -183,6 +184,7 @@ class VersionBitsTester
183184
184185 VersionBitsTester& TestDefined () { return TestState (ThresholdState::DEFINED); }
185186 VersionBitsTester& TestStarted () { return TestState (ThresholdState::STARTED); }
187+ VersionBitsTester& TestLastChance () { return TestState (ThresholdState::LAST_CHANCE); }
186188 VersionBitsTester& TestLockedIn () { return TestState (ThresholdState::LOCKED_IN); }
187189 VersionBitsTester& TestActive () { return TestState (ThresholdState::ACTIVE); }
188190 VersionBitsTester& TestFailed () { return TestState (ThresholdState::FAILED); }
@@ -200,40 +202,32 @@ BOOST_FIXTURE_TEST_SUITE(versionbits_tests, TestingSetup)
200202BOOST_AUTO_TEST_CASE(versionbits_test)
201203{
202204 for (int i = 0 ; i < 64 ; i++) {
203- // DEFINED -> FAILED
205+ // DEFINED -> LAST_CHANCE -> FAILED
204206 VersionBitsTester ().TestDefined ().TestStateSinceHeight (0 )
205207 .Mine (1 , TestTime (1 ), 0x100 ).TestDefined ().TestStateSinceHeight (0 )
206208 .Mine (11 , TestTime (11 ), 0x100 ).TestDefined ().TestStateSinceHeight (0 )
207209 .Mine (989 , TestTime (989 ), 0x100 ).TestDefined ().TestStateSinceHeight (0 )
208210 .Mine (999 , TestTime (20000 ), 0x100 ).TestDefined ().TestStateSinceHeight (0 )
209- .Mine (1000 , TestTime (20000 ), 0x100 ).TestFailed ().TestStateSinceHeight (1000 )
210- .Mine (1999 , TestTime (30001 ), 0x100 ).TestFailed ().TestStateSinceHeight (1000 )
211- .Mine (2000 , TestTime (30002 ), 0x100 ).TestFailed ().TestStateSinceHeight (1000 )
212- .Mine (2001 , TestTime (30003 ), 0x100 ).TestFailed ().TestStateSinceHeight (1000 )
213- .Mine (2999 , TestTime (30004 ), 0x100 ).TestFailed ().TestStateSinceHeight (1000 )
214- .Mine (3000 , TestTime (30005 ), 0x100 ).TestFailed ().TestStateSinceHeight (1000 )
215-
216- // DEFINED -> STARTED -> FAILED
211+ .Mine (1000 , TestTime (20000 ), 0x100 ).TestLastChance ().TestStateSinceHeight (1000 )
212+ .Mine (1999 , TestTime (30001 ), 0 ).TestLastChance ().TestStateSinceHeight (1000 )
213+ .Mine (2000 , TestTime (30002 ), 0x100 ).TestFailed ().TestStateSinceHeight (2000 )
214+ .Mine (2001 , TestTime (30003 ), 0x100 ).TestFailed ().TestStateSinceHeight (2000 )
215+ .Mine (2999 , TestTime (30004 ), 0x100 ).TestFailed ().TestStateSinceHeight (2000 )
216+ .Mine (3000 , TestTime (30005 ), 0x100 ).TestFailed ().TestStateSinceHeight (2000 )
217+ .Mine (4000 , TestTime (30006 ), 0x100 ).TestFailed ().TestStateSinceHeight (2000 )
218+
219+ // DEFINED -> STARTED -> LAST_CHANCE -> FAILED
217220 .Reset ().TestDefined ().TestStateSinceHeight (0 )
218221 .Mine (1 , TestTime (1 ), 0 ).TestDefined ().TestStateSinceHeight (0 )
219222 .Mine (1000 , TestTime (10000 ) - 1 , 0x100 ).TestDefined ().TestStateSinceHeight (0 ) // One second more and it would be defined
220223 .Mine (2000 , TestTime (10000 ), 0x100 ).TestStarted ().TestStateSinceHeight (2000 ) // So that's what happens the next period
221224 .Mine (2051 , TestTime (10010 ), 0 ).TestStarted ().TestStateSinceHeight (2000 ) // 51 old blocks
222225 .Mine (2950 , TestTime (10020 ), 0x100 ).TestStarted ().TestStateSinceHeight (2000 ) // 899 new blocks
223- .Mine (3000 , TestTime (20000 ), 0 ).TestFailed ().TestStateSinceHeight (3000 ) // 50 old blocks (so 899 out of the past 1000)
224- .Mine (4000 , TestTime (20010 ), 0x100 ).TestFailed ().TestStateSinceHeight (3000 )
225-
226- // DEFINED -> STARTED -> FAILED while threshold reached
227- .Reset ().TestDefined ().TestStateSinceHeight (0 )
228- .Mine (1 , TestTime (1 ), 0 ).TestDefined ().TestStateSinceHeight (0 )
229- .Mine (1000 , TestTime (10000 ) - 1 , 0x101 ).TestDefined ().TestStateSinceHeight (0 ) // One second more and it would be defined
230- .Mine (2000 , TestTime (10000 ), 0x101 ).TestStarted ().TestStateSinceHeight (2000 ) // So that's what happens the next period
231- .Mine (2999 , TestTime (30000 ), 0x100 ).TestStarted ().TestStateSinceHeight (2000 ) // 999 new blocks
232- .Mine (3000 , TestTime (30000 ), 0x100 ).TestFailed ().TestStateSinceHeight (3000 ) // 1 new block (so 1000 out of the past 1000 are new)
233- .Mine (3999 , TestTime (30001 ), 0 ).TestFailed ().TestStateSinceHeight (3000 )
234- .Mine (4000 , TestTime (30002 ), 0 ).TestFailed ().TestStateSinceHeight (3000 )
235- .Mine (14333 , TestTime (30003 ), 0 ).TestFailed ().TestStateSinceHeight (3000 )
236- .Mine (24000 , TestTime (40000 ), 0 ).TestFailed ().TestStateSinceHeight (3000 )
226+ .Mine (3000 , TestTime (20000 ), 0 ).TestLastChance ().TestStateSinceHeight (3000 ) // 50 old blocks (so 899 out of the past 1000)
227+ .Mine (3051 , TestTime (20010 ), 0 ).TestLastChance ().TestStateSinceHeight (3000 ) // 51 old blocks
228+ .Mine (3950 , TestTime (20030 ), 0x100 ).TestLastChance ().TestStateSinceHeight (3000 ) // 899 new blocks
229+ .Mine (4000 , TestTime (30000 ), 0 ).TestFailed ().TestStateSinceHeight (4000 ) // 50 old blocks (so 899 out of the past 1000)
230+ .Mine (5000 , TestTime (30010 ), 0x100 ).TestFailed ().TestStateSinceHeight (4000 )
237231
238232 // DEFINED -> STARTED -> LOCKEDIN at the last minute -> ACTIVE
239233 .Reset ().TestDefined ()
@@ -251,16 +245,26 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
251245 .Mine (6000 , TestTime (40002 ), 0 ).TestActive ().TestStateSinceHeight (4000 , 6000 )
252246 .Mine (15000 , TestTime (40000 ), 0 ).TestActive ().TestStateSinceHeight (4000 , 6000 )
253247
254- // DEFINED multiple periods -> STARTED multiple periods -> FAILED
248+ // DEFINED -> LAST_CHANCE -> LOCKEDIN -> ACTIVE
249+ .Reset ().TestDefined ()
250+ .Mine (1 , TestTime (1 ), 0 ).TestDefined ().TestStateSinceHeight (0 )
251+ .Mine (1000 , TestTime (40000 ), 0 ).TestLastChance ().TestStateSinceHeight (1000 )
252+ .Mine (1999 , TestTime (40010 ), 0x100 ).TestLastChance ().TestStateSinceHeight (1000 )
253+ .Mine (2000 , TestTime (40020 ), 0 ).TestLockedIn ().TestStateSinceHeight (2000 )
254+ .Mine (3000 , TestTime (40030 ), 0 ).TestActive ().TestStateSinceHeight (3000 )
255+ .Mine (5000 , TestTime (40030 ), 0 ).TestActive ().TestStateSinceHeight (3000 )
256+
257+ // DEFINED multiple periods -> STARTED multiple periods -> LAST_CHANCE -> FAILED
255258 .Reset ().TestDefined ().TestStateSinceHeight (0 )
256259 .Mine (999 , TestTime (999 ), 0 ).TestDefined ().TestStateSinceHeight (0 )
257260 .Mine (1000 , TestTime (1000 ), 0 ).TestDefined ().TestStateSinceHeight (0 )
258261 .Mine (2000 , TestTime (2000 ), 0 ).TestDefined ().TestStateSinceHeight (0 )
259262 .Mine (3000 , TestTime (10000 ), 0 ).TestStarted ().TestStateSinceHeight (3000 )
260263 .Mine (4000 , TestTime (10000 ), 0 ).TestStarted ().TestStateSinceHeight (3000 )
261264 .Mine (5000 , TestTime (10000 ), 0 ).TestStarted ().TestStateSinceHeight (3000 )
262- .Mine (6000 , TestTime (20000 ), 0 ).TestFailed ().TestStateSinceHeight (6000 )
263- .Mine (7000 , TestTime (20000 ), 0x100 ).TestFailed ().TestStateSinceHeight (6000 )
265+ .Mine (6000 , TestTime (20000 ), 0 ).TestLastChance ().TestStateSinceHeight (6000 )
266+ .Mine (7000 , TestTime (30000 ), 0 ).TestFailed ().TestStateSinceHeight (7000 )
267+ .Mine (8000 , TestTime (40000 ), 0x100 ).TestFailed ().TestStateSinceHeight (7000 )
264268 ;
265269 }
266270}
@@ -282,18 +286,13 @@ BOOST_AUTO_TEST_CASE(versionbits_sanity)
282286 BOOST_CHECK_EQUAL (mainnetParams.vDeployments [i].min_lock_in_time , 0 );
283287 }
284288
285- // Verify that the deployment windows of different deployment using the
286- // same bit are disjoint.
287- // This test may need modification at such time as a new deployment
288- // is proposed that reuses the bit of an activated soft fork, before the
289- // end time of that soft fork. (Alternatively, the end time of that
290- // activated soft fork could be later changed to be earlier to avoid
291- // overlap.)
289+ // Verify that the different deployments do not use the same bit.
290+ // Because of LAST_CHANCE signalling it is not possible to
291+ // guarantee that future time frames are disjoint otherwise.
292+ // Past deployments should be deleted (if FAILED) or buried
293+ // (if ACTIVE) so that their bits may be reused.
292294 for (int j=i+1 ; j<(int ) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; j++) {
293- if (VersionBitsMask (mainnetParams, static_cast <Consensus::DeploymentPos>(j)) == bitmask) {
294- BOOST_CHECK (mainnetParams.vDeployments [j].nStartTime > mainnetParams.vDeployments [i].nTimeout ||
295- mainnetParams.vDeployments [i].nStartTime > mainnetParams.vDeployments [j].nTimeout );
296- }
295+ BOOST_CHECK (VersionBitsMask (mainnetParams, static_cast <Consensus::DeploymentPos>(j)) != bitmask);
297296 }
298297 }
299298}
@@ -405,14 +404,14 @@ void check_computeblockversion(const Consensus::Params& params, Consensus::Deplo
405404 nHeight += 1 ;
406405 }
407406
408- // FAILED is only triggered at the end of a period, so CBV should be setting
409- // the bit until the period transition .
410- for (uint32_t i = 0 ; i < params.nMinerConfirmationWindow - 1 ; i++) {
407+ // we do two periods: the last STARTED period, where
408+ // MTP hits nTimeout and the LAST_CHANCE period .
409+ for (uint32_t i = 0 ; i < 2 * params.nMinerConfirmationWindow - 1 ; i++) {
411410 lastBlock = firstChain.Mine (nHeight+1 , nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip ();
412411 BOOST_CHECK ((ComputeBlockVersion (lastBlock, params) & (1 <<bit)) != 0 );
413412 nHeight += 1 ;
414413 }
415- // The next block should trigger no longer setting the bit.
414+ // The next block should hit FAILED and no longer trigger setting the bit.
416415 lastBlock = firstChain.Mine (nHeight+1 , nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip ();
417416 BOOST_CHECK_EQUAL (ComputeBlockVersion (lastBlock, params) & (1 <<bit), 0 );
418417 }
0 commit comments