Skip to content

Commit a82b7b2

Browse files
authored
Implement interim DAA hardfork (#46)
* Implement interim DAA hardfork * Bury deadpool and hard diff removal deployments * Regtest: Bring up test framework and fix gHash impl * Bring up mining_basic.py * Make it possible to test DAA interim hardfork on regtest * Remove block solve log print and support dynamic nBits * Use C-based integer factorization in regtest * Use C-based whirlpool impl in regtest if available * Halve interim DAA interval and vote threshold * Fix off-by-one error * Correctness fixes * Fix mining_basic.py * Add feature_interim_daa.py * Fix mining_basic.py again * Pre-flight fixes * Lower testnet diff for faster testing * Fix comment
1 parent 13178c0 commit a82b7b2

15 files changed

Lines changed: 745 additions & 118 deletions

src/chainparams.cpp

Lines changed: 48 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ class CMainParams : public CChainParams {
9494
consensus.CSVHeight = 1;
9595
consensus.SegwitHeight = 1;
9696
consensus.TaprootHeight = 1;
97+
consensus.DeadpoolHeight = 157248;
98+
consensus.HardDiffRemovalHeight = 168672;
9799
consensus.MinBIP9WarningHeight = 1; // segwit activation height + miner confirmation window
98100
consensus.powLimit = 230;
99101
consensus.nPowTargetTimespan = 14ULL * 24ULL * 60ULL * 60ULL; // 14 Days * 24 Hours * 60 Minutes * 60 Seconds |-> Seconds in 2 weeks.
@@ -118,22 +120,19 @@ class CMainParams : public CChainParams {
118120
//Number of rounds for gHash to generate random Ws around which to search for semiprimes.
119121
consensus.hashRounds = 1;
120122

121-
// Deadpool softfork
122-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].bit = 27;
123-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].nStartTime = 1735689600LL; // 2025-01-01
124-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].nTimeout = 1748736000LL; // 2025-06-01
125-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].min_activation_height = 155000; // no delay
126-
127123
// Deadpool parametrization
128124
consensus.nDeadpoolAnnounceMaturity = 100;
129125
consensus.nDeadpoolAnnounceValidity = 672;
130126
consensus.nDeadpoolAnnounceMinBurn = 1000000; // 0.01 COIN
131127

132-
// Hard diff removal hardfork
133-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].bit = 26;
134-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].nStartTime = 1743465600LL; // 2025-04-01
135-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].nTimeout = 1775001600LL; // 2026-04-01
136-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].min_activation_height = 160000; // no delay
128+
// Interim DAA hardfork
129+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].bit = 25;
130+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nStartTime = 1767225600LL; // 2026-01-01
131+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nTimeout = 1784505600LL; // 2026-07-20
132+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].min_activation_height = 0;
133+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nPeriod = Consensus::INTERIM_DAA_PERIOD;
134+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nThreshold = Consensus::INTERIM_DAA_THRESHOLD;
135+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].max_active_blocks = Consensus::INTERIM_DAA_MAX_ACTIVE;
137136

138137
/**
139138
* The message start string is designed to be unlikely to occur in normal data.
@@ -207,7 +206,7 @@ class CTestNetParams : public CChainParams {
207206
public:
208207
CTestNetParams() {
209208
strNetworkID = CBaseChainParams::TESTNET;
210-
genesis = CreateGenesisBlock( 1650442708ULL, 4143631544ULL, 210, 0, -2813, 0);
209+
genesis = CreateGenesisBlock( 1650443545ULL, 2706135317ULL, 32, 0, 254, 0);
211210
consensus.hashGenesisBlock = genesis.GetHash();
212211
consensus.signet_blocks = false;
213212
consensus.signet_challenge.clear();
@@ -218,8 +217,10 @@ class CTestNetParams : public CChainParams {
218217
consensus.CSVHeight = 1;
219218
consensus.SegwitHeight = 1;
220219
consensus.TaprootHeight = 1;
220+
consensus.DeadpoolHeight = 1;
221+
consensus.HardDiffRemovalHeight = 1;
221222
consensus.MinBIP9WarningHeight = 1; // segwit activation height + miner confirmation window
222-
consensus.powLimit = 210;
223+
consensus.powLimit = 32;
223224
consensus.nPowTargetTimespan = 24 * 60 * 60; // two weeks
224225
consensus.nPowTargetSpacing = 5 * 60;
225226
consensus.fPowAllowMinDifficultyBlocks = true;
@@ -238,22 +239,19 @@ class CTestNetParams : public CChainParams {
238239
//Number of Miller-Rabin rounds, determines primality with false positive rate of 4^(-rounds).
239240
consensus.MillerRabinRounds = 50 ;
240241

241-
// Deadpool softfork
242-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].bit = 27;
243-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].nStartTime = 1735689600LL; // Jan 1st, 2025
244-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
245-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].min_activation_height = 0; // No activation delay
246-
247242
// Deadpool parametrization
248243
consensus.nDeadpoolAnnounceMaturity = 5;
249244
consensus.nDeadpoolAnnounceValidity = 100;
250245
consensus.nDeadpoolAnnounceMinBurn = 1000000; // 0.01 COIN
251246

252-
// Hard diff removal hardfork
253-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].bit = 26;
254-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].nStartTime = 0;
255-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
256-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].min_activation_height = (4 * consensus.nMinerConfirmationWindow);
247+
// Interim DAA hardfork
248+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].bit = 25;
249+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nStartTime = 1767225600LL; // 2026-01-01
250+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
251+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].min_activation_height = 0;
252+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nPeriod = Consensus::INTERIM_DAA_PERIOD;
253+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nThreshold = Consensus::INTERIM_DAA_THRESHOLD;
254+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].max_active_blocks = Consensus::INTERIM_DAA_MAX_ACTIVE;
257255

258256
//Number of rounds for gHash to generate random Ws around which to search for semiprimes.
259257
consensus.hashRounds = 1;
@@ -269,8 +267,8 @@ class CTestNetParams : public CChainParams {
269267

270268
//Assert for genesis block.
271269
consensus.hashGenesisBlock = genesis.GetHash();
272-
assert(consensus.hashGenesisBlock == uint256S("550bbf0a444d9f92189f067dd225f5b8a5d92587ebc2e8398d143236072580af"));
273-
assert(genesis.hashMerkleRoot == uint256S("fe56b75eb001df55cfe63e768ff54a7a376a3108119c9cedd1c6b5045649b108"));
270+
// assert(consensus.hashGenesisBlock == uint256S("550bbf0a444d9f92189f067dd225f5b8a5d92587ebc2e8398d143236072580af"));
271+
// assert(genesis.hashMerkleRoot == uint256S("fe56b75eb001df55cfe63e768ff54a7a376a3108119c9cedd1c6b5045649b108"));
274272

275273
//Seeds
276274
vFixedSeeds.clear();
@@ -292,8 +290,8 @@ class CTestNetParams : public CChainParams {
292290

293291
checkpointData = {
294292
{
295-
{0, uint256S("550bbf0a444d9f92189f067dd225f5b8a5d92587ebc2e8398d143236072580af") },
296-
{3990, uint256S("ecb678bcb76dfe655b69ff3b9094be33c6f3dac118fe58bd7dff57e62e28c7c2") }
293+
// {0, uint256S("550bbf0a444d9f92189f067dd225f5b8a5d92587ebc2e8398d143236072580af") },
294+
// {3990, uint256S("ecb678bcb76dfe655b69ff3b9094be33c6f3dac118fe58bd7dff57e62e28c7c2") }
297295
}
298296
};
299297

@@ -372,6 +370,8 @@ class SigNetParams : public CChainParams {
372370
consensus.CSVHeight = 1;
373371
consensus.SegwitHeight = 1;
374372
consensus.TaprootHeight = 1;
373+
consensus.DeadpoolHeight = 1;
374+
consensus.HardDiffRemovalHeight = 1;
375375
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
376376
consensus.nPowTargetSpacing = 30 * 60;
377377
consensus.fPowAllowMinDifficultyBlocks = false;
@@ -401,22 +401,19 @@ class SigNetParams : public CChainParams {
401401
//Number of rounds for gHash to generate random Ws around which to search for semiprimes.
402402
consensus.hashRounds = 1;
403403

404-
// Deadpool softfork
405-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].bit = 27;
406-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].nStartTime = 0;
407-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
408-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].min_activation_height = (4 * consensus.nMinerConfirmationWindow); // Add one more epoch than required
409-
410404
// Deadpool parametrization
411405
consensus.nDeadpoolAnnounceMaturity = 5;
412406
consensus.nDeadpoolAnnounceValidity = 100;
413407
consensus.nDeadpoolAnnounceMinBurn = 1000000; // 0.01 COIN
414408

415-
// Hard diff removal hardfork
416-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].bit = 26;
417-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].nStartTime = 1743465600LL; // 2025-04-01
418-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].nTimeout = 1775001600LL; // 2026-04-01
419-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].min_activation_height = 160000; // no delay
409+
// Interim DAA hardfork
410+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].bit = 25;
411+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nStartTime = 1767225600LL; // 2026-01-01
412+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
413+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].min_activation_height = 0;
414+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nPeriod = Consensus::INTERIM_DAA_PERIOD;
415+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nThreshold = Consensus::INTERIM_DAA_THRESHOLD;
416+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].max_active_blocks = Consensus::INTERIM_DAA_MAX_ACTIVE;
420417

421418
vFixedSeeds.clear();
422419
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111);
@@ -453,12 +450,14 @@ class CRegTestParams : public CChainParams {
453450
consensus.CSVHeight = 1;
454451
consensus.SegwitHeight = 1;
455452
consensus.TaprootHeight = 1;
453+
consensus.DeadpoolHeight = 1;
454+
consensus.HardDiffRemovalHeight = 1;
456455
consensus.MinBIP9WarningHeight = 0;
457456
consensus.powLimit = 32;
458457
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
459458
consensus.nPowTargetSpacing = 30 * 60;
460-
consensus.fPowAllowMinDifficultyBlocks = true;
461-
consensus.fPowNoRetargeting = true;
459+
consensus.fPowAllowMinDifficultyBlocks = false;
460+
consensus.fPowNoRetargeting = false;
462461
consensus.nRuleChangeActivationThreshold = 24; // 75% for testchains
463462
consensus.nMinerConfirmationWindow = 32; // Faster than normal for regtest (32 instead of 2016)
464463

@@ -485,22 +484,19 @@ class CRegTestParams : public CChainParams {
485484
//Number of rounds for gHash to generate random Ws around which to search for semiprimes.
486485
consensus.hashRounds = 1;
487486

488-
// Deadpool softfork
489-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].bit = 27;
490-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].nStartTime = 0;
491-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
492-
consensus.vDeployments[Consensus::DEPLOYMENT_DEADPOOL].min_activation_height = (4 * consensus.nMinerConfirmationWindow); // Add one more epoch than required
493-
494487
// Deadpool parametrization
495488
consensus.nDeadpoolAnnounceMaturity = 5;
496489
consensus.nDeadpoolAnnounceValidity = 100;
497490
consensus.nDeadpoolAnnounceMinBurn = 1000000; // 0.01 COIN
498491

499-
// Hard diff removal hardfork
500-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].bit = 26;
501-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].nStartTime = 1743465600LL; // 2025-04-01
502-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].nTimeout = 1775001600LL; // 2026-04-01
503-
consensus.vDeployments[Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL].min_activation_height = 160000; // no delay
492+
// Interim DAA hardfork
493+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].bit = 25;
494+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nStartTime = 0;
495+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
496+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].min_activation_height = 0;
497+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nPeriod = Consensus::INTERIM_DAA_PERIOD;
498+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].nThreshold = Consensus::INTERIM_DAA_THRESHOLD;
499+
consensus.vDeployments[Consensus::DEPLOYMENT_INTERIM_DAA].max_active_blocks = Consensus::INTERIM_DAA_MAX_ACTIVE;
504500

505501
UpdateActivationParametersFromArgs(args);
506502

src/consensus/params.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@ enum BuriedDeployment : int16_t {
2323
DEPLOYMENT_CSV,
2424
DEPLOYMENT_SEGWIT,
2525
DEPLOYMENT_TAPROOT,
26+
DEPLOYMENT_DEADPOOL,
27+
DEPLOYMENT_HARD_DIFF_REMOVAL,
2628
};
27-
constexpr bool ValidDeployment(BuriedDeployment dep) { return dep <= DEPLOYMENT_TAPROOT; }
29+
constexpr bool ValidDeployment(BuriedDeployment dep) { return dep <= DEPLOYMENT_HARD_DIFF_REMOVAL; }
2830

2931
enum DeploymentPos : uint16_t {
3032
DEPLOYMENT_TESTDUMMY,
31-
DEPLOYMENT_DEADPOOL,
32-
DEPLOYMENT_HARD_DIFF_REMOVAL,
33+
DEPLOYMENT_INTERIM_DAA,
3334
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp
3435
MAX_VERSION_BITS_DEPLOYMENTS
3536
};
@@ -50,6 +51,12 @@ struct BIP9Deployment {
5051
* boundary.
5152
*/
5253
int min_activation_height{0};
54+
/** Per-deployment voting period override. 0 = use global nMinerConfirmationWindow */
55+
int nPeriod{0};
56+
/** Per-deployment threshold override. 0 = use global nRuleChangeActivationThreshold */
57+
int nThreshold{0};
58+
/** Auto-deactivate after this many blocks post-activation. 0 = permanent */
59+
int max_active_blocks{0};
5360

5461
/** Constant for nTimeout very far in the future. */
5562
static constexpr int64_t NO_TIMEOUT = std::numeric_limits<int64_t>::max();
@@ -66,6 +73,11 @@ struct BIP9Deployment {
6673
static constexpr int64_t NEVER_ACTIVE = -2;
6774
};
6875

76+
/** Constants for interim DAA deployment */
77+
static constexpr int INTERIM_DAA_PERIOD = 42;
78+
static constexpr int INTERIM_DAA_THRESHOLD = 40; // 95% of 42
79+
static constexpr int INTERIM_DAA_MAX_ACTIVE = 1344; // 2 normal epochs
80+
6981
/**
7082
* Parameters that influence chain consensus.
7183
*/
@@ -87,6 +99,10 @@ struct Params {
8799
* BIP 16 exception blocks. */
88100
int SegwitHeight;
89101
int TaprootHeight;
102+
/** Block height at which Deadpool becomes active */
103+
int DeadpoolHeight;
104+
/** Block height at which Hard Diff Removal becomes active */
105+
int HardDiffRemovalHeight;
90106
/** Don't warn about unknown BIP 9 activations below this height.
91107
* This prevents us from warning about the CSV and segwit activations. */
92108
int MinBIP9WarningHeight;
@@ -151,6 +167,10 @@ struct Params {
151167
return SegwitHeight;
152168
case DEPLOYMENT_TAPROOT:
153169
return TaprootHeight;
170+
case DEPLOYMENT_DEADPOOL:
171+
return DeadpoolHeight;
172+
case DEPLOYMENT_HARD_DIFF_REMOVAL:
173+
return HardDiffRemovalHeight;
154174
} // no default case, so the compiler can warn about missing cases
155175
return std::numeric_limits<int>::max();
156176
}

src/deploymentinfo.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@ const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_B
1212
/*.gbt_force =*/ true,
1313
},
1414
{
15-
/*.name =*/ "deadpool",
16-
/*.gbt_force =*/ true,
17-
},
18-
{
19-
/*.name =*/ "hard_diff_removal",
15+
/*.name =*/ "interim_daa",
2016
/*.gbt_force =*/ true,
2117
},
2218
};
@@ -37,6 +33,10 @@ std::string DeploymentName(Consensus::BuriedDeployment dep)
3733
return "segwit";
3834
case Consensus::DEPLOYMENT_TAPROOT:
3935
return "taproot";
36+
case Consensus::DEPLOYMENT_DEADPOOL:
37+
return "deadpool";
38+
case Consensus::DEPLOYMENT_HARD_DIFF_REMOVAL:
39+
return "hard_diff_removal";
4040
} // no default case, so the compiler can warn about missing cases
4141
return "";
4242
}

src/deploymentstatus.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,21 @@ inline bool DeploymentEnabled(const Consensus::Params& params, Consensus::Deploy
5252
return params.vDeployments[dep].nStartTime != Consensus::BIP9Deployment::NEVER_ACTIVE;
5353
}
5454

55+
/** Check if a time-limited deployment is active */
56+
inline bool TimeLimitedDeploymentActive(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos dep)
57+
{
58+
if (!DeploymentActiveAfter(pindexPrev, params, dep)) {
59+
return false;
60+
}
61+
62+
int maxActive = params.vDeployments[dep].max_active_blocks;
63+
if (maxActive <= 0) {
64+
return true;
65+
}
66+
67+
int activationHeight = g_versionbitscache.StateSinceHeight(pindexPrev, params, dep);
68+
int currentHeight = (pindexPrev == nullptr) ? 0 : pindexPrev->nHeight + 1;
69+
return currentHeight < activationHeight + maxActive;
70+
}
71+
5572
#endif // BITCOIN_DEPLOYMENTSTATUS_H

0 commit comments

Comments
 (0)