{"number":94,"title":"Testnet 4","authors":["Fabian Jahr"],"status":"Deployed","type":"Specification","layer":"Applications","created":"2024-05-27","license":"CC0-1.0","requires":[],"replaces":[],"replacedBy":[95],"discussion":["https://gnusha.org/pi/bitcoindev/CADL_X_eXjbRFROuJU0b336vPVy5Q2RJvhcx64NSNPH-3fDCUfw@mail.gmail.com/","https://gnusha.org/pi/bitcoindev/a6e3VPsXJf9p3gt_FmNF_Up-wrFuNMKTN30-xCSDHBKXzXnSpVflIZIj2NQ8Wos4PhQCzI2mWEMvIms_FAEs7rQdL15MpC_Phmu_fnR9iTg=@protonmail.com/","https://github.com/bitcoin/bitcoin/pull/29775"],"abstract":"A new test network with the goal to replace Testnet 3. This network comes with small but important improvements of the consensus rules, that should make it impractical to attack the network using only CPU mining.","eli5":"Defines Testnet 4, a replacement for the long-running Testnet 3 practice network, where coins have no value and developers test software. It tightens a few rules to stop attackers from disrupting the network cheaply with ordinary computers, making testing more reliable.","categories":["consensus","mining"],"filename":"bip-0094.mediawiki","githubUrl":"https://github.com/bitcoin/bips/blob/master/bip-0094.mediawiki","format":"mediawiki","readingMinutes":6,"inbound":1,"revisions":15,"impact":51,"core":false,"references":[],"lastModified":"2025-10-08","html":"<h2 id=\"abstract\">Abstract</h2>\n<p>A new test network with the goal to replace Testnet 3. This network comes with small but important improvements of the consensus rules, that should make it impractical to attack the network using only CPU mining.</p>\n<h2 id=\"motivation\">Motivation</h2>\n<p>Quoting the original mailing list post from Jameson Lopp<sup class=\"footnote-ref\"><a href=\"#fn-1\" id=\"fnref-1\">[1]</a></sup>:</p>\n<blockquote><poem> Testnet3 has been running for 13 years. It's on block 2.5 million something and the block reward is down to ~0.014 TBTC, so mining is not doing a great job at distributing testnet coins anymore.\n<p>The reason the block height is insanely high is due to a rather amusing edge case bug that causes the difficulty to regularly get reset to 1, which causes a bit of havoc. If you want a deep dive into the quirk: <a href=\"https://blog.lopp.net/the-block-storms-of-bitcoins-testnet/\">https://blog.lopp.net/the-block-storms-of-bitcoins-testnet/</a></p>\n<p>Testnet3 is being actively used for scammy airdrops; those of us who tend to be generous with our testnet coins are getting hounded by non-developers chasing cheap gains.</p>\n<p>As a result, TBTC is being actively bought and sold; one could argue that the fundamental principle of testnet coins having no value has been broken. </poem></blockquote></p>\n<p>Since then the issue with block storms has been further demonstrated on Testnet 3 when three years' worth of blocks were mined in a few weeks while rendering the network practically unusable at the same time.</p>\n<h2 id=\"specification\">Specification</h2>\n<p>Testnet 4 follows the same consensus rules as mainnet with the following three exceptions. Additionally, all soft forks that are active on mainnet as of May 2024 are enforced from genesis.</p>\n<h3 id=\"1-20-minute-exception-rule\">1. 20-minute Exception Rule</h3>\n<p>This rule was implemented in Testnet 3<sup class=\"footnote-ref\"><a href=\"#fn-2\" id=\"fnref-2\">[2]</a></sup> and is preserved in Testnet 4.</p>\n<h4 id=\"rule-specification\">Rule Specification</h4>\n<p>1. For any block except the first block in a difficulty period:    a. If the block's timestamp is >20 minutes past the timestamp of the previous block    b. Then the block MUST use the minimum difficulty value (<code>nBits</code> = <code>0x1d00ffff</code>), regardless of the network's actual difficulty</p>\n<p>2. The first block of each difficulty period MUST use the actual network difficulty.</p>\n<p>This rule enables CPU mining on testnet but has led to block storms<sup class=\"footnote-ref\"><a href=\"#fn-3\" id=\"fnref-3\">[3]</a></sup> which rule #2 below addresses.</p>\n<h3 id=\"2-block-storm-fix\">2. Block Storm Fix</h3>\n<p>This is a new rule to address block storms caused by the 20-minute exception.</p>\n<h4 id=\"problem-statement\">Problem Statement</h4>\n<p>In Mainnet and Testnet 3, the difficulty adjustment calculation uses the difficulty value of the last block in the previous period as its base. When the 20-minute exception is applied to this last block, it is mined at difficulty 1, causing the next period's difficulty to be constrained between 1-4, leading to block storms.</p>\n<h4 id=\"rule-specification-1\">Rule Specification</h4>\n<p>1. For difficulty adjustment calculations between periods:    a. The base difficulty value MUST be taken from the first block of the previous difficulty period    b. NOT from the last block as in previous implementations</p>\n<p>2. The adjustment factor calculation remains unchanged:    a. Multiplication factor based on the duration of the previous difficulty period    b. Limited to no less than 1/4 and no more than 4x</p>\n<p>This change ensures that the actual network difficulty is used for adjustment calculations rather than potentially manipulated values from the last block in a period.</p>\n<h3 id=\"3-time-warp-attack-prevention\">3. Time Warp Attack Prevention</h3>\n<p>This rule prevents time warp attacks that could otherwise be used to amplify block storms<sup class=\"footnote-ref\"><a href=\"#fn-4\" id=\"fnref-4\">[4]</a></sup>.</p>\n<h4 id=\"rule-specification-2\">Rule Specification</h4>\n<p>1. For any block whose height modulo 2016 equals 0 (i.e., the first block of each difficulty period):    a. The block's <code>nTime</code> field MUST be greater than or equal to the <code>nTime</code> field of the immediately prior block minus 600 seconds</p>\n<p>2. These blocks MUST still comply with existing Median-Time-Past <code>nTime</code> restrictions</p>\n<p>This rule is based on The Great Consensus Cleanup proposal<sup class=\"footnote-ref\"><a href=\"#fn-5\" id=\"fnref-5\">[5]</a></sup> and prevents miners from manipulating timestamps to artificially lower difficulty.</p>\n<h2 id=\"rationale\">Rationale</h2>\n<p>The applied changes were the result of discussions on the mailing list and the PR. The selected changes try to strike a balance between minimal changes to the network (keeping it as close to mainnet as possible) while making it more robust against attackers that try to disrupt the network. Several alternative designs were considered:</p>\n<ul><li>\nFor the block storm fix an alternative fix could have been to prevent the last block in a difficulty period from applying the existing difficulty exception. Both solutions were deemed acceptable and there was no clear preference among reviewers.\n</li></ul>\n<ul><li>\nRemoval of the 20-minute exception was discussed but dismissed since several reviewers insisted that it was a useful feature allowing non-standard transactions to be mined with just a CPU. The 20-minute exception also allows CPU users to move the chain forward (except on the first block that needs to be mined at actual difficulty) in case a large amount of hash power suddenly leaves the network. This would allow the chain to recover to a normal difficulty level faster if left stranded at high difficulty.\n</li></ul>\n<ul><li>\nIncrease of minimum difficulty was discussed but dismissed as it would categorically prevent participation in the network using a CPU miner (utilizing the 20-minute exception).\n</li></ul>\n<ul><li>\nIncrease of the delay in the 20-minute exception was suggested but did not receive significant support.\n</li></ul>\n<ul><li>\nRe-enabling <code>acceptnonstdtxn</code> in bitcoin core by default was dismissed as it had led to confusion among layer-2s that had used testnet for transaction propagation tests and expected it to behave similarly to mainnet.\n</li></ul>\n<ul><li>\nMotivating miners to re-org min difficulty blocks was suggested, but was considered out of scope for this BIP, since adoption of such a mining policy remains available after Testnet 4 is deployed. As 20-minute exception blocks only contribute work corresponding to difficulty one to the chaintip, and actual difficulty blocks should have a difficulty magnitudes higher, a block mined at actual difficulty could easily replace even multiple 20-minute exception blocks.\n</li></ul>\n<ul><li>\nPersisting the real difficulty in the version field was suggested to robustly prevent exploits of the 20-minute exception while allowing it to be used on any block, but did not receive a sufficient level of support to justify the more invasive change.\n</li></ul>\n<p>One known downside of the chosen approach is that if the difficulty is gradually raised by a miner with significant hash rate, and this miner disappears, then each difficulty adjustment period requires one block at the actual difficulty.</p>\n<p>This would cause the network to stall once per difficulty adjustment period until the real difficulty is adjusted downwards enough for the remaining hash rate to find this block in reasonable time.</p>\n<h2 id=\"network-parameters\">Network Parameters</h2>\n<h3 id=\"consensus-rules\">Consensus Rules</h3>\n<p>All consensus rules active on mainnet at the time of this proposal are enforced from block 1, the newest of these rules being the Taproot softfork.</p>\n<h3 id=\"genesis-block\">Genesis Block</h3>\n<ul><li>\nMessage: <code>03/May/2024 000000000000000000001ebd58c244970b3aa9d783bb001011fbe8ea8e98e00e</code>\n</li></ul>\n<ul><li>\nPubkey: <code>000000000000000000000000000000000000000000000000000000000000000000</code>\n</li></ul>\n<ul><li>\nTime stamp: 1714777860\n</li></ul>\n<ul><li>\nNonce: 393743547\n</li></ul>\n<ul><li>\nDifficulty: <code>0x1d00ffff</code>\n</li></ul>\n<ul><li>\nVersion: 1\n</li></ul>\n<p>The resulting genesis block hash is <code>00000000da84f2bafbbc53dee25a72ae507ff4914b867c565be350b0da8bf043</code>, and the block hex is <code>0100000000000000000000000000000000000000000000000000000000000000000000004e7b2b9128fe0291db0693af2ae418b767e657cd407e80cb1434221eaea7a07a046f3566ffff001dbb0c78170101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff5504ffff001d01044c4c30332f4d61792f323032342030303030303030303030303030303030303030303165626435386332343439373062336161396437383362623030313031316662653865613865393865303065ffffffff0100f2052a010000002321000000000000000000000000000000000000000000000000000000000000000000ac00000000</code>.</p>\n<h3 id=\"message-start\">Message Start</h3>\n<p>The message start is defined as <code>0x1c163f28</code>. These four bytes were randomly generated and have no special meaning.</p>\n<h3 id=\"network-parameters-1\">Network Parameters</h3>\n<p>The default p2p port for Testnet 4 is `48333`.</p>\n<h2 id=\"backwards-compatibility\">Backwards Compatibility</h2>\n<p>The rules used by Testnet 4 are backwards compatible to the rules of Testnet 3. Existing software that implements support for Testnet 3 would only require addition of the network parameters  (magic number, genesis block, etc.) to be able to follow Testnet 4.</p>\n<p>However, implementations that only implement Testnet 3's rules would accept a chain that violates Testnet 4's rules and are therefore susceptible to being forked off. It is recommended that any implementations check blocks in regard to all the new rules of Testnet 4 and reject blocks that fail to comply.</p>\n<h2 id=\"reference-implementation\">Reference implementation</h2>\n<p>Pull request at <a href=\"https://github.com/bitcoin/bitcoin/pull/29775\">https://github.com/bitcoin/bitcoin/pull/29775</a></p>\n<h2 id=\"references\">References</h2>\n<ol class=\"footnotes\"><li id=\"fn-1\"><a href=\"https://gnusha.org/pi/bitcoindev/CADL_X_eXjbRFROuJU0b336vPVy5Q2RJvhcx64NSNPH-3fDCUfw@mail.gmail.com/\">https://gnusha.org/pi/bitcoindev/CADL_X_eXjbRFROuJU0b336vPVy5Q2RJvhcx64NSNPH-3fDCUfw@mail.gmail.com/</a> <a href=\"#fnref-1\" class=\"footnote-back\" aria-label=\"Back to text\">↩</a></li><li id=\"fn-2\"><a href=\"https://github.com/bitcoin/bitcoin/pull/686\">https://github.com/bitcoin/bitcoin/pull/686</a> <a href=\"#fnref-2\" class=\"footnote-back\" aria-label=\"Back to text\">↩</a></li><li id=\"fn-3\"><a href=\"https://blog.lopp.net/the-block-storms-of-bitcoins-testnet/\">https://blog.lopp.net/the-block-storms-of-bitcoins-testnet/</a> <a href=\"#fnref-3\" class=\"footnote-back\" aria-label=\"Back to text\">↩</a></li><li id=\"fn-4\">A perpetual block storm attack with entire difficulty periods being authored in less than 3.5 days that resets the difficulty to the minimum in the last block of every difficulty period would adjust to a new actual difficulty of 4 every period. An attacker that additionally leverages a time warp attack would start their attack by holding back timestamps until the latest block's timestamp is at least two weeks in the past, and then limiting their block rate to six blocks per second, incrementing the timestamp on every sixth block. Only on the last block they would use the current time, which both resets the difficulty to one per the 20-minute exception and would result in a difficulty adjustment keeping the difficulty at the minimum due to the elapsed time exceeding the target. This would allow lower the difficulty for all blocks to difficulty 1 instead of difficulty 4 <a href=\"#fnref-4\" class=\"footnote-back\" aria-label=\"Back to text\">↩</a></li><li id=\"fn-5\"><a href=\"https://github.com/TheBlueMatt/bips/blob/cleanup-softfork/bip-XXXX.mediawiki\">https://github.com/TheBlueMatt/bips/blob/cleanup-softfork/bip-XXXX.mediawiki</a> <a href=\"#fnref-5\" class=\"footnote-back\" aria-label=\"Back to text\">↩</a></li></ol>\n<h2 id=\"copyright\">Copyright</h2>\n<p>This document is licensed under the  Creative Commons CC0 1.0 Universal license.</p>","toc":[{"id":"abstract","title":"Abstract","level":2},{"id":"motivation","title":"Motivation","level":2},{"id":"specification","title":"Specification","level":2},{"id":"1-20-minute-exception-rule","title":"1. 20-minute Exception Rule","level":3},{"id":"rule-specification","title":"Rule Specification","level":4},{"id":"2-block-storm-fix","title":"2. Block Storm Fix","level":3},{"id":"problem-statement","title":"Problem Statement","level":4},{"id":"rule-specification-1","title":"Rule Specification","level":4},{"id":"3-time-warp-attack-prevention","title":"3. Time Warp Attack Prevention","level":3},{"id":"rule-specification-2","title":"Rule Specification","level":4},{"id":"rationale","title":"Rationale","level":2},{"id":"network-parameters","title":"Network Parameters","level":2},{"id":"consensus-rules","title":"Consensus Rules","level":3},{"id":"genesis-block","title":"Genesis Block","level":3},{"id":"message-start","title":"Message Start","level":3},{"id":"network-parameters-1","title":"Network Parameters","level":3},{"id":"backwards-compatibility","title":"Backwards Compatibility","level":2},{"id":"reference-implementation","title":"Reference implementation","level":2},{"id":"references","title":"References","level":2},{"id":"copyright","title":"Copyright","level":2}],"history":{"totalCommits":15,"firstCommit":"2024-05-27T23:23:06+02:00","lastUpdated":"2025-10-08T14:59:36-07:00","events":[{"sha":"24e96e870fffaa257b465ce1f0370c14aac588e8","date":"2025-10-08T14:59:36-07:00","author":"Murch","message":"process: Created ↦ Assigned","url":"https://github.com/bitcoin/bips/commit/24e96e870fffaa257b465ce1f0370c14aac588e8","kind":"edit"},{"sha":"5207ef92a52d0b8902895b0dbb40823a4d698ec9","date":"2025-04-11T20:08:17-07:00","author":"Murch","message":"process: Author ↦ Authors","url":"https://github.com/bitcoin/bips/commit/5207ef92a52d0b8902895b0dbb40823a4d698ec9","kind":"edit"},{"sha":"59730dec4fb641a41589aa1b91d3c452f13e0e36","date":"2025-04-11T20:05:13-07:00","author":"Murch","message":"process: Remove Comments-URI and -Summary","url":"https://github.com/bitcoin/bips/commit/59730dec4fb641a41589aa1b91d3c452f13e0e36","kind":"edit"},{"sha":"01352f7f40cb7f61d0aa177341f8804de2f8fed9","date":"2025-04-11T20:07:37-07:00","author":"Murch","message":"process: Post-History ↦ Discussion","url":"https://github.com/bitcoin/bips/commit/01352f7f40cb7f61d0aa177341f8804de2f8fed9","kind":"edit"},{"sha":"a233bde4af52c6a11269e2e6dd9707abce441ffe","date":"2025-04-11T18:19:21-07:00","author":"Murch","message":"process: Standards Track ↦ Specification","url":"https://github.com/bitcoin/bips/commit/a233bde4af52c6a11269e2e6dd9707abce441ffe","kind":"edit"},{"sha":"5d3ceb37734f80b2ec206fc94245e3bfd6d5b0f0","date":"2025-04-11T18:08:44-07:00","author":"Murch","message":"process: Final/Active ↦ Deployed","url":"https://github.com/bitcoin/bips/commit/5d3ceb37734f80b2ec206fc94245e3bfd6d5b0f0","kind":"status"},{"sha":"8137279570c2d38c8dda12c9654deed7f700c63c","date":"2025-04-17T15:46:10+08:00","author":"Jon Atack","message":"Monthly typo fixups","url":"https://github.com/bitcoin/bips/commit/8137279570c2d38c8dda12c9654deed7f700c63c","kind":"edit"},{"sha":"954a78ea1f8d8baaa93a1241a1dc5d42be704d84","date":"2025-03-07T14:43:23-06:00","author":"Jon Atack","message":"BIP94 PR1781 fixup","url":"https://github.com/bitcoin/bips/commit/954a78ea1f8d8baaa93a1241a1dc5d42be704d84","kind":"edit"},{"sha":"0dd4d3ec61305610454e976cd5e92a7fb23c34e1","date":"2025-03-06T15:08:11-08:00","author":"Olaoluwa Osuntokun","message":"BIP-0094: reformat specification section for clarity and readability","url":"https://github.com/bitcoin/bips/commit/0dd4d3ec61305610454e976cd5e92a7fb23c34e1","kind":"edit"},{"sha":"fcd5d7224e026adf7278861c73fc1d22330b4c0e","date":"2025-03-06T14:47:20-08:00","author":"Olaoluwa Osuntokun","message":"BIP-0094: add default p2p port for testnet4","url":"https://github.com/bitcoin/bips/commit/fcd5d7224e026adf7278861c73fc1d22330b4c0e","kind":"edit"},{"sha":"d2cfbae4c124dfebb534f78db0f0b23196cc73e7","date":"2025-02-25T16:39:24-05:00","author":"Fabian Jahr","message":"BIP 94: Move to Final","url":"https://github.com/bitcoin/bips/commit/d2cfbae4c124dfebb534f78db0f0b23196cc73e7","kind":"status"},{"sha":"2c259b85fd33593fd3028c5fdbc9abddea388fef","date":"2024-08-15T11:06:37+02:00","author":"Fabian Jahr","message":"Revert \"Change BIP 94 timewarp delta to 7200 seconds\"","url":"https://github.com/bitcoin/bips/commit/2c259b85fd33593fd3028c5fdbc9abddea388fef","kind":"edit"},{"sha":"af9557b589df19508e1b6937346a4b9724bd90d8","date":"2024-08-10T10:19:39+09:00","author":"azuchi","message":"BIP-0094: fix block hex","url":"https://github.com/bitcoin/bips/commit/af9557b589df19508e1b6937346a4b9724bd90d8","kind":"edit"},{"sha":"0c2a2172f76d05ecfdf55fed5650cc3ebaddb34a","date":"2024-08-05T23:05:30+02:00","author":"Fabian Jahr","message":"Change BIP 94 timewarp delta to 7200 seconds","url":"https://github.com/bitcoin/bips/commit/0c2a2172f76d05ecfdf55fed5650cc3ebaddb34a","kind":"edit"},{"sha":"a35650e14e5e3afce269efa0926233c30871b140","date":"2024-05-27T23:23:06+02:00","author":"Fabian Jahr","message":"Add BIP 94 - Testnet 4","url":"https://github.com/bitcoin/bips/commit/a35650e14e5e3afce269efa0926233c30871b140","kind":"edit"}]}}