Upgrade Mechanism
Bitcoin Roots implements BIP-8 with a timelock height — upgrades activate at a predetermined block regardless of miner participation. This page covers the problem, the mechanism, and the implementation.
The Problem
Bitcoin Core currently uses BIP-9 versionbits for soft fork activation. The mechanism requires 95% of mining hash rate to signal support for a proposed upgrade within a 2-year signaling window. On the surface this seems democratic. In practice, it gives any single mining pool operator veto authority over protocol changes.
If a pool controls more than 5% of the hash rate, it can prevent an upgrade from ever reaching the 95% threshold. The pool does not need to actively oppose the change — it simply refuses to signal. The upgrade times out as FAILED.
The SegWit 2x saga demonstrated this vulnerability. Mining pool operators signaled for a block size increase that the broader community explicitly rejected. When the entities controlling hash rate can unilaterally propose or block changes, the protocol no longer belongs to its users.
The Mechanism
BIP-8 extends the versionbits mechanism with a timelock height. The behavior is simple:
If 95% of miners signal support before the timelock height, the upgrade activates early — identical to BIP-9. If miners fail to reach the threshold, the upgrade activates automatically when the chain reaches the timelock height. The critical difference: the upgrade cannot FAIL. It activates on schedule regardless.
Bitcoin Roots implements this by modifying the versionbits state machine in src/versionbits.cpp. When the current chain height reaches or exceeds the timelock height, the deployment state is forced to ThresholdState::LOCKED_IN before FAILED can occur.
// Bitcoin Roots — BIP-8 timelock override
// When timelock height is reached, force LOCKED_IN state
if (timelock_height != -1 && nHeight >= timelock_height) {
return ThresholdState::LOCKED_IN;
}
// Otherwise, proceed with standard BIP-9 signaling
// Miners can still accelerate, but cannot block
This is not a theoretical improvement. The BIP-8 mechanism itself activates via a buried deployment — a hardcoded activation height that all nodes recognize regardless of miner signaling. On Bitcoin Roots mainnet, BIP-8 becomes available at block 1,050,000.
Activation Heights
The BIP-8 mechanism is hardcoded per network. These heights are compiled into the binary and cannot be changed without recompiling:
| Network | BIP-8 Height | Approximate Date |
|---|---|---|
mainnet |
1,050,000 |
~mid-2026 |
testnet4 |
1,050,000 |
~mid-2026 |
signet |
1 |
immediate |
regtest |
1 |
immediate |
Signet and regtest use block 1 to enable immediate testing of the BIP-8 mechanism in development and test environments.
Implementation
Five files for the BIP-8 mechanism. Every change is documented below.
Defines the DEPLOYMENT_BIP8 enum entry in VBDeployment, adds nTimelockHeight to the BIP9Deployment struct, and adds the BIP8_ACTIVATION_HEIGHT member with a DeploymentHeight() accessor case to the Params class.
Declares TimelockHeight() as a virtual method on VersionBitsConditionChecker. Returns the timelock height for a given deployment — or -1 if the deployment does not use BIP-8.
Implements VersionBitsConditionChecker::TimelockHeight() override and modifies the STARTED state transition. When nHeight >= timelock_height, forces ThresholdState::LOCKED_IN before FAILED can occur. This is the core behavioral change.
Sets BIP8_ACTIVATION_HEIGHT and configures DEPLOYMENT_BIP8 in the vDeployments array for each network class: CMainParams, CTestNetParams, CSignetParams, CRegTestParams.
Adds DEPLOYMENT_BIP8 to the deployment name lookup table and reverse mapping. Required for RPC and logging to reference the deployment by name.
Safety
The nTimelockHeight field on BIP9Deployment is only populated for buried deployments via DEPLOYMENT_BIP8. Regular BIP-9 deployments always have a timelock height of -1. This is intentional — it prevents accidental BIP-8 activation on deployments that were designed as miner-signaled upgrades.
On Bitcoin Core v25.0, chain parameters use a class-based approach (CMainParams, etc.) rather than the functional ApplyDeploymentOptions pattern. The versionbits module also lacks the PIMPL pattern — all implementation lives in versionbits.h and versionbits.cpp. This affects how the patches are structured compared to a master-branch port.
The BIP-8 timelock does not bypass consensus. It removes the ability for miners to block activation, but the underlying soft fork rules still require standard compliance. Nodes that do not recognize the new rules simply see them as standard transactions they can verify.