What's going on with testnet4?
Introduction
Testnet4 BIP94 is a test network that mimics Bitcoin’s “production” network, but coins should have no value, and therefore can be used for testing. It differs from signet in that it tries to be as close to mainnet as possible, allowing everyone to mine on it, with the same standardness rules and with unpredictable difficulty adjustments.
It was proposed after testnet3, it’s predecessor, was found broken for two reason:
- Testnet coins should have no value, if they become widely traded it’s a sign that testnet isn’t working as a testnet anymore
- Blockstorms are really easy to trigger and this may annoy some applications
With testnet 4 we fixed the former simply by resetting the network to an early reward time, where we get 50 bitcoins every block. The latter was fixed by making the re-target algorithm looking back on blocks until it finds the actual network difficulty.
It was officially deployed in Bitcoin Core v28.0 and the genesis block was mined by the PR’s author in May 3rd, 2024. After the proposed BIP and code was set, someone found a way to still timewarp testnet 4, even with the fixes. This was later fixed before merging testnet 4 in Bitcoin Core.
But now, someone is doing the exact opposite: abusing the rules to make it so difficult to mine new blocks, that an old S9 would take almost a day to mine a single block. To understand this, we need to understand how Bitcoin sees time.
PoW and time
In Bitcoin’s Proof-of-Work, time is really important, because it is used by the network to change the network’s difficulty and keep block production in a pre-defined window (10 min avg). But we can’t have consensus on the exact time a block was found - that’s why we need the whole blockchain and PoW thing. Instead, miners claim the time they started working on a block, and this time is used in the re-target alg. However what happens if miners lie about it?
Well, they can’t change things about the chian ordering (change the order of two blocks, for example), but they can mess with the re-target algorithm. They can either undershoot their time (claiming a time that’s in the past) and cause the difficulty to go up. Or they can overshoot, and make the difficulty go down. While the Bitcoin consensus does have some upper and lower bounds to this, there are still some possible attacks that can be achieved here.
Every block should obey two rules for it’s timestamp field:
- A block time must not be greater than two hours into the future from this node’s clock. This rule is problematic because it can cause a consensus failure, should clocks on a subsection of the network be off by a few hours. Luckily, this isn’t usually a problem, as computers are pretty good at keeping their clock in-sync. But if you change your computer’s time to either too far into the past or future, bitcoind
will give a gently warning that you might fail to validate some blocks (or your may accept a block that your peers wont’).
- A block time must be greater than the median of the last 11 block’s timestamp. This one was introduced in BIP113 and is mostly to protect time-locked transaction against miners claiming this block is too into the past to make a transaction valid/invalid
Anything between [MTP - T+2h] is a valid time. How can we take advantage of this to mess with the re-target?
The problem with testnet 4
While the older problems are fixed, we still have one on the table: someone is using the 20 min rule to get testnet’s difficulty to unreasonable levels of difficult, making it hard to find a block with full difficulty, while mining all diff 1 blocks almost instantly. The result is that a single entity now is mining the overwhelming majority of blocks on testnet 4. Getting all the new coins and making it impossible for testers to find blocks by their own.
By unreasonably high difficulty, I mean a difficulty that doesn’t reflect the current hashrate. You can see this in the fact that blocks with full difficulty may take days to be found!
But how does that work? To understand this, say we are at block 10. Anyone can pretend their blocks are over 20 minutes into the future and use the diff 1 rule. In fact, I’ve made a (terrible) code that exploits this and mines testnet blocks for you using only a CPU. But you have a limit, the way this is implemented is that the difference between the last block’s time and current must be greater than 20 minutes. So the first block using this exploit are 20 minutes into the future, but the second needs to be 40 minutes into the future (20 from block 11), and the next 60, 80, 100, 120. After 120 you hit the 2h rule and can’t proceed. So using this exploit, you can find up to 6 blocks. Then, in the next hour you can find 3 more. But 6 blocks is the expected for just one hour. No problem here, right?
Well, remember that the only thing we use to check the 20min rule is the last block’s timestamp. Now, if someone finds a non 1-diff block, with the timestamp close to wall time, we find an extra 6 blocks starting from the current timestamp + 20.
In the following picture, white blocks have full difficulty, pink are diff 1 blocks. Let’s assume that finding diff 1 blocks is instantaneous. Without a new white block, we’ll have 7 blocks in two hours (we expect 12, so we’re cool!).
But if we have another white block, even if some time has passed (like 5 min), we’ll end up with almost 14 blocks in two hours. If we got more white blocks, we would get way more pinks, with roughly 6 pink block for each white. Even though those blocks are special in that they can be found more easily, they still count. Therefore, we’ll reach the re-target block way earlier than we should, causing the difficulty to skyrocket (as the network thinks we have a way bigger hashrate). Repeat this until you get a difficulty so high that even an S9 would take about a day to find a block. That’s how someone broke testnet 4.
When I last looked at it, the difficulty was 121 million. That’s way smaller than the almost 100 trillion for mainnet, but still respectable. The difficulty we see in block explorers are a multiple, usually of 4294967296 this is what we call diff 1, it’s the minimum difficulty possible in Bitcoin.
You can obtain this number by dividing $2 ^ {256}$ by consensus.powLimit.
This number means that (on average) you need $x \times 4294967296 $ hashes until you find a block solution. The bigger the value, the harder it gets. $121M = 4294967296 \times 121M = 519691042816000000$ hashes to find a solution. I have an old Dragonmint T1
laying around, and I’ve tried to find a normal diff block. But even though it makes about 16 trillion hashes every second, it would still take $~32480$ seconds to find a block or $~9h$. I’ve left it running for 5h, twice. Couldn’t hit a single block :/
mempool.space claims the network hashrate to be about 150.5TH/s
. If we want to have blocks every ten minutes (avg), the difficulty would need to be $\frac {(150T * 600)}{4294967296} = 20954757$ or about 5x
smaller than the ATH. At the time of writing, the difficulty seems to be subsiding, with the next adjustment estimated to get a 29% reduction in the difficulty, but still in a pretty high level.