Technical brief · Testnet4 Letter for miners

Soft fork on testnet4 that fixes the min difficulty blocks exploit

A targeted, height-activated change that makes BIP 94's min-difficulty escape hatch unreachable.

Summary. Invalidate any non-difficulty-adjustment block whose timestamp is more than 20 minutes than its previous block's timestamp, after block height 151,200 (epoch 75 boundary, ~September 6th 2026).

§1 Problem

Testnet4's min-difficulty rule (allowing difficulty-1 blocks after 20 minutes) is being exploited, causing ~85-90% of blocks to be CPU-mined min-difficulty blocks. This results in a race of CPU miners broadcasting blocks at exactly the second that it's acceptable. This race is so intense that CPU miners have figured out sending empty blocks, as they propagate faster than those that contain transactions, resulting in a network where transactions are confirmed at only the remaining ASIC blocks, that have ~1 hour average block times.

After the fork, min difficulty blocks will no longer be allowed, as blocks that have a timestamp longer than 20 minutes than their previous blocks become invalid, except difficulty-adjusting blocks (epoch boundary blocks).

This change is intentionally a soft fork, so that it also fixes the problem for non-upgraded nodes as long as majority of the hashrate is mining on upgraded clients, with the least network disruption.

§2 What miners need to do

Run your miner against a patched Bitcoin Core node. Any node enforcing the new rules will also produce compliant block templates. The patched branch is testnet4-softfork on github.com/batmanbytes/bitcoin.

2.1   Install build dependencies linux

On Debian or Ubuntu:

sudo apt update
sudo apt install build-essential cmake pkgconf python3 \
                 libevent-dev libboost-dev libsqlite3-dev \
                 git ca-certificates \
                 capnproto libcapnp-dev

On macOS with Homebrew, the equivalent is brew install cmake pkgconf boost libevent sqlite capnp. For other distributions and full dependency detail see doc/build-*.md in the cloned repository.

2.2   Clone the patched branch

git clone -b testnet4-softfork \
  https://github.com/batmanbytes/bitcoin.git
cd bitcoin

Or, if you already have a clone of bitcoin/bitcoin, add this fork as a remote and check out the branch:

git remote add batmanbytes https://github.com/batmanbytes/bitcoin.git
git fetch batmanbytes
git checkout batmanbytes/testnet4-softfork

2.3   Configure and build

cmake -B build
cmake --build build

The resulting binaries land in build/bin/.

2.4   Start the node on testnet4

./build/bin/bitcoind -testnet4 -daemon

Point your mining stack at this node for getblocktemplate. Once the chain reaches height 151 200 the new rule activates automatically; no further action required.

§3 Activation

The soft fork activates on testnet4 by at block height 151 200. No version-bits signalling is involved.

Chaintestnet4
Activation height151 200 (epoch 75)
Consensus parametermin_difficulty_blocks_fix_height
Default on other chains0 (disabled)
Mechanismheight flag-day, no signalling

Previously-valid blocks at heights below the activation height are unaffected: history does not change. An non-upgraded node that produces a cap-violating block at height ≥ 151 201 will find that upgraded nodes reject it, causing a short-lived fork until the non-upgraded miner upgrades or is outpaced. Miners are strongly encouraged to upgrade before activation.

§4 Specification

4.1   Consensus check consensus

For every block at or above the activation height, the following must hold:

block.nTime ≤ pindexPrev->nTime + 2 * nPowTargetSpacing

On testnet4, nPowTargetSpacing = 600, so the cap is 1200 s. A block that violates the cap is rejected with reason string time-too-far-ahead. The rule is a strict tightening of the existing validation rules, therefore a soft fork: every block that is valid under the new rule was also valid under the old rule.

4.2   Adjustment-block carve-out consensus

The cap is not enforced on blocks whose height is divisible by DifficultyAdjustmentInterval() (2016). On such blocks the retargeted difficulty is always required, regardless of timestamp, so no exploit exists to close. Capping adjustment-block timestamps would therefore serve no purpose, and would prevent miners from publishing truthful wall-clock time on the one block per retarget period where they would otherwise be free to do so.

4.3   Template-side clamp mining

A matching clamp is applied in node/miner so that getblocktemplate and the internal block assembler never return a curtime that would be rejected by §4.1. The helper is GetMaximumTime(pindexPrev, consensus), mirroring the existing GetMinimumTime. On adjustment blocks it returns INT64_MAX, matching the consensus carve-out in §4.2.

§5 References