What changed, and why it matters
This commit cleans up Bitcoin Core's code after Taproot has already activated. It removes Taproot's old activation parameters from the list of live BIP9 deployments and from the getdeploymentinfo RPC, because those parameters are no longer needed now that the rules are enforced. It also makes sure getblocktemplate still tells miners the 'taproot' rule is required. There is no direct security vulnerability here; it is routine post-activation maintenance, though any consensus-cleanup change carries a small risk of accidental behavior change.
Review as normal consensus-cleanup maintenance. Verify that getblocktemplate still advertises the taproot rule correctly and that no active consensus enforcement logic was accidentally removed. No urgent security action is indicated.
Security signals we found
Consensus deployment parameter removal for an activated soft fork
BIP9 warning threshold adjustment to suppress historical activation warnings
getblocktemplate rule list change affecting miner template compatibility
RPC output change (getdeploymentinfo no longer reports taproot)
No bug fix, boundary check, memory safety, or cryptographic change present
Evidence from the diff
The change drops DEPLOYMENT_TAPROOT from Consensus::DeploymentPos and from VersionBitsDeploymentInfo, removes Taproot’s BIP9 deployment configuration from mainnet/testnet/signet/regtest chainparams, and removes it from getdeploymentinfo’s output. MinBIP9WarningHeight is bumped to taproot activation height + one retarget window on mainnet and testnet so the client does not warn about the now-historical Taproot activation. getblocktemplate is updated to explicitly include ‘taproot’ in the rules array when segwit is present, and tests are added/updated accordingly. The commit clarifies that consensus rules enforced from genesis are not listed as BuriedDeployments.
Changed components
src/consensus/params.hsrc/deploymentinfo.cppsrc/kernel/chainparams.cppsrc/rpc/blockchain.cppsrc/rpc/mining.cpptest/functional/mining_basic.pytest/functional/rpc_blockchain.pyInspect captured patch +23 / −63
diff --git a/doc/release-notes-26201.md b/doc/release-notes-26201.md
new file mode 100644
index 00000000..66c9da54
--- /dev/null
+++ b/doc/release-notes-26201.md
@@ -0,0 +1,4 @@
+RPC
+---
+
+- 'taproot' has been removed from 'getdeploymentinfo' because its historical activation height is no longer used anywhere in the codebase. (#26201)
diff --git a/src/consensus/params.h b/src/consensus/params.h
index 93ee071f..7f567294 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -20,6 +20,7 @@ namespace Consensus {
/**
* A buried deployment is one where the height of the activation has been hardcoded into
* the client implementation long after the consensus change has activated. See BIP 90.
+ * Consensus changes for which the new rules are enforced from genesis are not listed here.
*/
enum BuriedDeployment : int16_t {
// buried deployments get negative values to avoid overlap with DeploymentPos
@@ -27,14 +28,16 @@ enum BuriedDeployment : int16_t {
DEPLOYMENT_CLTV,
DEPLOYMENT_DERSIG,
DEPLOYMENT_CSV,
+ // SCRIPT_VERIFY_WITNESS is enforced from genesis, but the check for downloading
+ // missing witness data is not. BIP 147 also relies on hardcoded activation height.
DEPLOYMENT_SEGWIT,
};
constexpr bool ValidDeployment(BuriedDeployment dep) { return dep <= DEPLOYMENT_SEGWIT; }
enum DeploymentPos : uint16_t {
DEPLOYMENT_TESTDUMMY,
- DEPLOYMENT_TAPROOT, // Deployment of Schnorr/Taproot (BIPs 340-342)
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp
+ // Removing an entry may require bumping MinBIP9WarningHeight.
MAX_VERSION_BITS_DEPLOYMENTS
};
constexpr bool ValidDeployment(DeploymentPos dep) { return dep < MAX_VERSION_BITS_DEPLOYMENTS; }
@@ -105,7 +108,7 @@ struct Params {
* BIP 16 exception blocks. */
int SegwitHeight;
/** Don't warn about unknown BIP 9 activations below this height.
- * This prevents us from warning about the CSV and segwit activations. */
+ * This prevents us from warning about the CSV, segwit and taproot activations. */
int MinBIP9WarningHeight;
std::array<BIP9Deployment,MAX_VERSION_BITS_DEPLOYMENTS> vDeployments;
/** Proof of work parameters */
diff --git a/src/deploymentinfo.cpp b/src/deploymentinfo.cpp
index e1447d4d..551982b2 100644
--- a/src/deploymentinfo.cpp
+++ b/src/deploymentinfo.cpp
@@ -13,10 +13,6 @@ const std::array<VBDeploymentInfo,Consensus::MAX_VERSION_BITS_DEPLOYMENTS> Versi
.name = "testdummy",
.gbt_optional_rule = true,
},
- VBDeploymentInfo{
- .name = "taproot",
- .gbt_optional_rule = true,
- },
};
std::string DeploymentName(Consensus::BuriedDeployment dep)
diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp
index 64809a75..02c7ae9d 100644
--- a/src/kernel/chainparams.cpp
+++ b/src/kernel/chainparams.cpp
@@ -92,7 +92,7 @@ public:
consensus.BIP66Height = 363725; // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931
consensus.CSVHeight = 419328; // 000000000000000004a1b34462cb8aeebd5799177f7a29cf28f2d1961716b5b5
consensus.SegwitHeight = 481824; // 0000000000000000001c8018d9cb3b742ef25114f27563e3fc4a1902167f9893
- consensus.MinBIP9WarningHeight = 483840; // segwit activation height + miner confirmation window
+ consensus.MinBIP9WarningHeight = 711648; // taproot activation height + miner confirmation window
consensus.powLimit = uint256{"00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"};
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
@@ -106,14 +106,6 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1815; // 90%
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016;
- // Deployment of Taproot (BIPs 340-342)
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2;
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = 1619222400; // April 24th, 2021
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1628640000; // August 11th, 2021
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 709632; // Approximately November 12th, 2021
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1815; // 90%
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016;
-
consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000001128750f82f4c366153a3a030"};
consensus.defaultAssumeValid = uint256{"00000000000000000000ccebd6d74d9194d8dcdc1d177c478e094bfad51ba5ac"}; // 938343
@@ -223,7 +215,7 @@ public:
consensus.BIP66Height = 330776; // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182
consensus.CSVHeight = 770112; // 00000000025e930139bac5c6c31a403776da130831ab85be56578f3fa75369bb
consensus.SegwitHeight = 834624; // 00000000002b980fcd729daaa248fd9316a5200e9b367f4ff2c42453e84201ca
- consensus.MinBIP9WarningHeight = 836640; // segwit activation height + miner confirmation window
+ consensus.MinBIP9WarningHeight = 2013984; // taproot activation height + miner confirmation window
consensus.powLimit = uint256{"00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"};
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
@@ -237,14 +229,6 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1512; // 75%
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016;
- // Deployment of Taproot (BIPs 340-342)
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2;
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = 1619222400; // April 24th, 2021
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1628640000; // August 11th, 2021
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1512; // 75%
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016;
-
consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000000000017dde1c649f3708d14b6"};
consensus.defaultAssumeValid = uint256{"000000007a61e4230b28ac5cb6b5e5a0130de37ac1faf2f8987d2fa6505b67f4"}; // 4842348
@@ -345,14 +329,6 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1512; // 75%
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016;
- // Deployment of Taproot (BIPs 340-342)
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2;
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1512; // 75%
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016;
-
consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000000000009a0fe15d0177d086304"};
consensus.defaultAssumeValid = uint256{"0000000002368b1e4ee27e2e85676ae6f9f9e69579b29093e9a82c170bf7cf8a"}; // 123613
@@ -496,14 +472,6 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1815; // 90%
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016;
- // Activation of Taproot (BIPs 340-342)
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2;
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1815; // 90%
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016;
-
// message start is defined as the first 4 bytes of the sha256d of the block script
HashWriter h{};
h << consensus.signet_challenge;
@@ -586,13 +554,6 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 108; // 75%
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 144; // Faster than normal for regtest (144 instead of 2016)
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2;
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 108; // 75%
- consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 144;
-
consensus.nMinimumChainWork = uint256{};
consensus.defaultAssumeValid = uint256{};
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index d97b7c6c..f1a22f45 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1481,7 +1481,6 @@ UniValue DeploymentInfo(const CBlockIndex* blockindex, const ChainstateManager&
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_CSV);
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_SEGWIT);
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_TESTDUMMY);
- SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_TAPROOT);
return softforks;
}
} // anon namespace
@@ -1489,7 +1488,8 @@ UniValue DeploymentInfo(const CBlockIndex* blockindex, const ChainstateManager&
RPCHelpMan getdeploymentinfo()
{
return RPCHelpMan{"getdeploymentinfo",
- "Returns an object containing various state info regarding deployments of consensus changes.",
+ "Returns an object containing various state info regarding deployments of consensus changes.\n"
+ "Consensus changes for which the new rules are enforced from genesis are not listed in \"deployments\".",
{
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Default{"hash of current chain tip"}, "The block hash at which to query deployment state"},
},
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 043e11ff..514be2e8 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -947,8 +947,14 @@ static RPCHelpMan getblocktemplate()
result.pushKV("capabilities", std::move(aCaps));
UniValue aRules(UniValue::VARR);
+ // See getblocktemplate changes in BIP 9:
+ // ! indicates a more subtle change to the block structure or generation transaction
+ // Otherwise clients may assume the rule will not impact usage of the template as-is.
aRules.push_back("csv");
- if (!fPreSegWit) aRules.push_back("!segwit");
+ if (!fPreSegWit) {
+ aRules.push_back("!segwit");
+ aRules.push_back("taproot");
+ }
if (consensusParams.signet_blocks) {
// indicate to miner that they must understand signet rules
// when attempting to mine with this template
diff --git a/test/functional/mining_basic.py b/test/functional/mining_basic.py
index 750dd42c..899f8705 100755
--- a/test/functional/mining_basic.py
+++ b/test/functional/mining_basic.py
@@ -436,6 +436,9 @@ class MiningTest(BitcoinTestFramework):
self.log.info("getblocktemplate: segwit rule must be set")
assert_raises_rpc_error(-8, "getblocktemplate must be called with the segwit rule set", node.getblocktemplate, {})
+ self.log.info("getblocktemplate: result should set the right rules")
+ assert_equal(['csv', '!segwit', 'taproot'], self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)['rules'])
+
self.log.info("submitblock: Test block decode failure")
assert_raises_rpc_error(-22, "Block decode failed", node.submitblock, block.serialize()[:-15].hex())
diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py
index cecd0c03..ca90cac9 100755
--- a/test/functional/rpc_blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -241,19 +241,6 @@ class BlockchainTest(BitcoinTestFramework):
},
'active': False
},
- 'taproot': {
- 'type': 'bip9',
- 'bip9': {
- 'start_time': -1,
- 'timeout': 9223372036854775807,
- 'min_activation_height': 0,
- 'status': 'active',
- 'status_next': 'active',
- 'since': 0,
- },
- 'height': 0,
- 'active': True
- }
}
})
Why this scored 20/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.