Skip to content

Commit 7db0961

Browse files
committed
Merge bitcoin/bitcoin#29039: versionbits refactoring
e301401 test: add IsActiveAfter tests for versionbits (Anthony Towns) 60950f7 versionbits: docstrings for BIP9Info (Anthony Towns) 7565563 tests: refactor versionbits fuzz test (Anthony Towns) 2e4e9b9 tests: refactor versionbits unit test (Anthony Towns) 525c00f versionbits: Expose VersionBitsConditionChecker via impl header (Anthony Towns) e74a704 versionbits: Expose StateName function (Anthony Towns) d00d1ed versionbits: Split out internal details into impl header (Anthony Towns) 37b9b67 versionbits: Simplify VersionBitsCache API (Anthony Towns) 1198e7d versionbits: Move BIP9 status logic for getblocktemplate to versionbits (Anthony Towns) b1e967c versionbits: Move getdeploymentinfo logic to versionbits (Anthony Towns) 3bd32c2 versionbits: Move WarningBits logic from validation to versionbits (Anthony Towns) 5da119e versionbits: Change BIP9Stats to uint32_t types (Anthony Towns) a679040 consensus/params: Move version bits period/threshold to bip9 param (Anthony Towns) e9d6170 versionbits: Remove params from AbstractThresholdConditionChecker (Anthony Towns) 9bc41f1 versionbits: Use std::array instead of C-style arrays (Anthony Towns) Pull request description: Increases the encapsulation/modularity of the versionbits code, moving more of the logic into the versionbits module rather than having it scattered across validation and rpc code. Updates unit/fuzz tests to test the actual code used rather than just a close approximation of it. ACKs for top commit: achow101: ACK e301401 TheCharlatan: Re-ACK e301401 darosior: ACK e301401 Tree-SHA512: 2978db5038354b56fa1dd6aafd511099e9c16504d6a88daeac2ff2702c87bcf3e55a32e2f0a7697e3de76963b68b9d5ede7976ee007e45862fa306911194496d
2 parents 51d7663 + e301401 commit 7db0961

15 files changed

+549
-420
lines changed

src/consensus/params.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <uint256.h>
1010

11+
#include <array>
1112
#include <chrono>
1213
#include <limits>
1314
#include <map>
@@ -52,6 +53,14 @@ struct BIP9Deployment {
5253
* boundary.
5354
*/
5455
int min_activation_height{0};
56+
/** Period of blocks to check signalling in (usually retarget period, ie params.DifficultyAdjustmentInterval()) */
57+
uint32_t period{2016};
58+
/**
59+
* Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period,
60+
* which is also used for BIP9 deployments.
61+
* Examples: 1916 for 95%, 1512 for testchains.
62+
*/
63+
uint32_t threshold{1916};
5564

5665
/** Constant for nTimeout very far in the future. */
5766
static constexpr int64_t NO_TIMEOUT = std::numeric_limits<int64_t>::max();
@@ -97,14 +106,7 @@ struct Params {
97106
/** Don't warn about unknown BIP 9 activations below this height.
98107
* This prevents us from warning about the CSV and segwit activations. */
99108
int MinBIP9WarningHeight;
100-
/**
101-
* Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period,
102-
* (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments.
103-
* Examples: 1916 for 95%, 1512 for testchains.
104-
*/
105-
uint32_t nRuleChangeActivationThreshold;
106-
uint32_t nMinerConfirmationWindow;
107-
BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS];
109+
std::array<BIP9Deployment,MAX_VERSION_BITS_DEPLOYMENTS> vDeployments;
108110
/** Proof of work parameters */
109111
uint256 powLimit;
110112
bool fPowAllowMinDifficultyBlocks;

src/deploymentinfo.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88

99
#include <string_view>
1010

11-
const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
12-
{
13-
/*.name =*/ "testdummy",
14-
/*.gbt_force =*/ true,
11+
const std::array<VBDeploymentInfo,Consensus::MAX_VERSION_BITS_DEPLOYMENTS> VersionBitsDeploymentInfo{
12+
VBDeploymentInfo{
13+
.name = "testdummy",
14+
.gbt_force = true,
1515
},
16-
{
17-
/*.name =*/ "taproot",
18-
/*.gbt_force =*/ true,
16+
VBDeploymentInfo{
17+
.name = "taproot",
18+
.gbt_force = true,
1919
},
2020
};
2121

src/deploymentinfo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <consensus/params.h>
99

10+
#include <array>
1011
#include <optional>
1112
#include <string>
1213

@@ -17,7 +18,7 @@ struct VBDeploymentInfo {
1718
bool gbt_force;
1819
};
1920

20-
extern const VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS];
21+
extern const std::array<VBDeploymentInfo,Consensus::MAX_VERSION_BITS_DEPLOYMENTS> VersionBitsDeploymentInfo;
2122

2223
std::string DeploymentName(Consensus::BuriedDeployment dep);
2324

src/deploymentstatus.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus
2020
inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos dep, VersionBitsCache& versionbitscache)
2121
{
2222
assert(Consensus::ValidDeployment(dep));
23-
return ThresholdState::ACTIVE == versionbitscache.State(pindexPrev, params, dep);
23+
return versionbitscache.IsActiveAfter(pindexPrev, params, dep);
2424
}
2525

2626
/** Determine if a deployment is active for this block */

src/kernel/chainparams.cpp

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,20 @@ class CMainParams : public CChainParams {
104104
consensus.fPowAllowMinDifficultyBlocks = false;
105105
consensus.enforce_BIP94 = false;
106106
consensus.fPowNoRetargeting = false;
107-
consensus.nRuleChangeActivationThreshold = 1815; // 90% of 2016
108-
consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
109107
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
110108
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
111109
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
112110
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay
111+
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1815; // 90%
112+
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016;
113113

114114
// Deployment of Taproot (BIPs 340-342)
115115
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2;
116116
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = 1619222400; // April 24th, 2021
117117
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1628640000; // August 11th, 2021
118118
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 709632; // Approximately November 12th, 2021
119+
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1815; // 90%
120+
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016;
119121

120122
consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000000b1f3b93b65b16d035a82be84"};
121123
consensus.defaultAssumeValid = uint256{"00000000000000000001b658dd1120e82e66d2790811f89ede9742ada3ed6d77"}; // 886157
@@ -216,18 +218,20 @@ class CTestNetParams : public CChainParams {
216218
consensus.fPowAllowMinDifficultyBlocks = true;
217219
consensus.enforce_BIP94 = false;
218220
consensus.fPowNoRetargeting = false;
219-
consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains
220-
consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
221221
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
222222
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
223223
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
224224
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay
225+
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1512; // 75%
226+
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016;
225227

226228
// Deployment of Taproot (BIPs 340-342)
227229
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2;
228230
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = 1619222400; // April 24th, 2021
229231
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1628640000; // August 11th, 2021
230232
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay
233+
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1512; // 75%
234+
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016;
231235

232236
consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000000000015f5e0c9f13455b0eb17"};
233237
consensus.defaultAssumeValid = uint256{"00000000000003fc7967410ba2d0a8a8d50daedc318d43e8baf1a9782c236a57"}; // 3974606
@@ -309,18 +313,21 @@ class CTestNet4Params : public CChainParams {
309313
consensus.fPowAllowMinDifficultyBlocks = true;
310314
consensus.enforce_BIP94 = true;
311315
consensus.fPowNoRetargeting = false;
312-
consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains
313-
consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
316+
314317
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
315318
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
316319
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
317320
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay
321+
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1512; // 75%
322+
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016;
318323

319324
// Deployment of Taproot (BIPs 340-342)
320325
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2;
321326
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
322327
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
323328
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay
329+
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1512; // 75%
330+
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016;
324331

325332
consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000000000001d6dce8651b6094e4c1"};
326333
consensus.defaultAssumeValid = uint256{"0000000000003ed4f08dbdf6f7d6b271a6bcffce25675cb40aa9fa43179a89f3"}; // 72600
@@ -439,20 +446,22 @@ class SigNetParams : public CChainParams {
439446
consensus.fPowAllowMinDifficultyBlocks = false;
440447
consensus.enforce_BIP94 = false;
441448
consensus.fPowNoRetargeting = false;
442-
consensus.nRuleChangeActivationThreshold = 1815; // 90% of 2016
443-
consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
444449
consensus.MinBIP9WarningHeight = 0;
445450
consensus.powLimit = uint256{"00000377ae000000000000000000000000000000000000000000000000000000"};
446451
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
447452
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
448453
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
449454
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay
455+
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1815; // 90%
456+
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016;
450457

451458
// Activation of Taproot (BIPs 340-342)
452459
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2;
453460
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
454461
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
455462
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay
463+
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1815; // 90%
464+
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016;
456465

457466
// message start is defined as the first 4 bytes of the sha256d of the block script
458467
HashWriter h{};
@@ -516,18 +525,20 @@ class CRegTestParams : public CChainParams
516525
consensus.fPowAllowMinDifficultyBlocks = true;
517526
consensus.enforce_BIP94 = opts.enforce_bip94;
518527
consensus.fPowNoRetargeting = true;
519-
consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains
520-
consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016)
521528

522529
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
523530
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0;
524531
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
525532
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay
533+
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 108; // 75%
534+
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 144; // Faster than normal for regtest (144 instead of 2016)
526535

527536
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2;
528537
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
529538
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
530539
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay
540+
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 108; // 75%
541+
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 144;
531542

532543
consensus.nMinimumChainWork = uint256{};
533544
consensus.defaultAssumeValid = uint256{};

src/rpc/blockchain.cpp

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,71 +1234,55 @@ static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softfo
12341234
static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const ChainstateManager& chainman, Consensus::DeploymentPos id)
12351235
{
12361236
// For BIP9 deployments.
1237-
12381237
if (!DeploymentEnabled(chainman, id)) return;
12391238
if (blockindex == nullptr) return;
12401239

1241-
auto get_state_name = [](const ThresholdState state) -> std::string {
1242-
switch (state) {
1243-
case ThresholdState::DEFINED: return "defined";
1244-
case ThresholdState::STARTED: return "started";
1245-
case ThresholdState::LOCKED_IN: return "locked_in";
1246-
case ThresholdState::ACTIVE: return "active";
1247-
case ThresholdState::FAILED: return "failed";
1248-
}
1249-
return "invalid";
1250-
};
1251-
12521240
UniValue bip9(UniValue::VOBJ);
1253-
1254-
const ThresholdState next_state = chainman.m_versionbitscache.State(blockindex, chainman.GetConsensus(), id);
1255-
const ThresholdState current_state = chainman.m_versionbitscache.State(blockindex->pprev, chainman.GetConsensus(), id);
1256-
1257-
const bool has_signal = (ThresholdState::STARTED == current_state || ThresholdState::LOCKED_IN == current_state);
1241+
BIP9Info info{chainman.m_versionbitscache.Info(*blockindex, chainman.GetConsensus(), id)};
1242+
const auto& depparams{chainman.GetConsensus().vDeployments[id]};
12581243

12591244
// BIP9 parameters
1260-
if (has_signal) {
1261-
bip9.pushKV("bit", chainman.GetConsensus().vDeployments[id].bit);
1245+
if (info.stats.has_value()) {
1246+
bip9.pushKV("bit", depparams.bit);
12621247
}
1263-
bip9.pushKV("start_time", chainman.GetConsensus().vDeployments[id].nStartTime);
1264-
bip9.pushKV("timeout", chainman.GetConsensus().vDeployments[id].nTimeout);
1265-
bip9.pushKV("min_activation_height", chainman.GetConsensus().vDeployments[id].min_activation_height);
1248+
bip9.pushKV("start_time", depparams.nStartTime);
1249+
bip9.pushKV("timeout", depparams.nTimeout);
1250+
bip9.pushKV("min_activation_height", depparams.min_activation_height);
12661251

12671252
// BIP9 status
1268-
bip9.pushKV("status", get_state_name(current_state));
1269-
bip9.pushKV("since", chainman.m_versionbitscache.StateSinceHeight(blockindex->pprev, chainman.GetConsensus(), id));
1270-
bip9.pushKV("status_next", get_state_name(next_state));
1253+
bip9.pushKV("status", info.current_state);
1254+
bip9.pushKV("since", info.since);
1255+
bip9.pushKV("status_next", info.next_state);
12711256

12721257
// BIP9 signalling status, if applicable
1273-
if (has_signal) {
1258+
if (info.stats.has_value()) {
12741259
UniValue statsUV(UniValue::VOBJ);
1275-
std::vector<bool> signals;
1276-
BIP9Stats statsStruct = chainman.m_versionbitscache.Statistics(blockindex, chainman.GetConsensus(), id, &signals);
1277-
statsUV.pushKV("period", statsStruct.period);
1278-
statsUV.pushKV("elapsed", statsStruct.elapsed);
1279-
statsUV.pushKV("count", statsStruct.count);
1280-
if (ThresholdState::LOCKED_IN != current_state) {
1281-
statsUV.pushKV("threshold", statsStruct.threshold);
1282-
statsUV.pushKV("possible", statsStruct.possible);
1260+
statsUV.pushKV("period", info.stats->period);
1261+
statsUV.pushKV("elapsed", info.stats->elapsed);
1262+
statsUV.pushKV("count", info.stats->count);
1263+
if (info.stats->threshold > 0 || info.stats->possible) {
1264+
statsUV.pushKV("threshold", info.stats->threshold);
1265+
statsUV.pushKV("possible", info.stats->possible);
12831266
}
12841267
bip9.pushKV("statistics", std::move(statsUV));
12851268

12861269
std::string sig;
1287-
sig.reserve(signals.size());
1288-
for (const bool s : signals) {
1270+
sig.reserve(info.signalling_blocks.size());
1271+
for (const bool s : info.signalling_blocks) {
12891272
sig.push_back(s ? '#' : '-');
12901273
}
12911274
bip9.pushKV("signalling", sig);
12921275
}
12931276

12941277
UniValue rv(UniValue::VOBJ);
12951278
rv.pushKV("type", "bip9");
1296-
if (ThresholdState::ACTIVE == next_state) {
1297-
rv.pushKV("height", chainman.m_versionbitscache.StateSinceHeight(blockindex, chainman.GetConsensus(), id));
1279+
bool is_active = false;
1280+
if (info.active_since.has_value()) {
1281+
rv.pushKV("height", *info.active_since);
1282+
is_active = (*info.active_since <= blockindex->nHeight + 1);
12981283
}
1299-
rv.pushKV("active", ThresholdState::ACTIVE == next_state);
1300-
rv.pushKV("bip9", std::move(bip9));
1301-
1284+
rv.pushKV("active", is_active);
1285+
rv.pushKV("bip9", bip9);
13021286
softforks.pushKV(DeploymentName(id), std::move(rv));
13031287
}
13041288

0 commit comments

Comments
 (0)