test: add block 2016 to mock mainnet

The next commit requires an additional mainnet block which changes the difficulty.

Also fix a few minor mistakes in the test (suite):
- rename the create_coinbase retarger_period argument to halving_period. Before bitcoin#31583 this was hardcoded for regtest where these values are the same.
- drop unused fees argument from mine helper

Finally the CPU miner instructions for generating the alternative mainnet chain are expanded.

Github-Pull: #33446
Rebased-From: 4c3c1f42cf
This commit is contained in:
Sjors Provoost
2025-09-20 21:32:41 +02:00
committed by fanquake
parent 72c1f13c33
commit 4ec30d53ec
4 changed files with 30 additions and 13 deletions

View File

@@ -11,9 +11,10 @@ The alternate mainnet chain was generated as follows:
- restart node with a faketime 2 minutes later - restart node with a faketime 2 minutes later
```sh ```sh
for i in {1..2015} for i in {1..2016}
do do
faketime "`date -d @"$(( 1231006505 + $i * 120 ))" +'%Y-%m-%d %H:%M:%S'`" \ t=$(( 1231006505 + $i * 120 ))
faketime "`date -d @$t +'%Y-%m-%d %H:%M:%S'`" \
bitcoind -connect=0 -nocheckpoints -stopatheight=$i bitcoind -connect=0 -nocheckpoints -stopatheight=$i
done done
``` ```
@@ -21,7 +22,9 @@ done
The CPU miner is kept running as follows: The CPU miner is kept running as follows:
```sh ```sh
./minerd --coinbase-addr 1NQpH6Nf8QtR2HphLRcvuVqfhXBXsiWn8r --no-stratum --algo sha256d --no-longpoll --scantime 3 --retry-pause 1 ./minerd -u ... -p ... -o http://127.0.0.1:8332 --no-stratum \
--coinbase-addr 1NQpH6Nf8QtR2HphLRcvuVqfhXBXsiWn8r \
--algo sha256d --no-longpoll --scantime 3 --retry-pause 1
``` ```
The payout address is derived from first BIP32 test vector master key: The payout address is derived from first BIP32 test vector master key:
@@ -40,3 +43,8 @@ The timestamp was not kept constant because at difficulty 1 it's not sufficient
to only grind the nonce. Grinding the extra_nonce or version field instead to only grind the nonce. Grinding the extra_nonce or version field instead
would have required additional (stratum) software. It would also make it more would have required additional (stratum) software. It would also make it more
complicated to reconstruct the blocks in this test. complicated to reconstruct the blocks in this test.
The `getblocktemplate` RPC code needs to be patched to ignore not being connected
to any peers, and to ignore the IBD status check.
On macOS use `faketime "@$t"` instead.

View File

@@ -2014,7 +2014,8 @@
1231247971, 1231247971,
1231248071, 1231248071,
1231248198, 1231248198,
1231248322 1231248322,
1231248621
], ],
"nonces": [ "nonces": [
2345621585, 2345621585,
@@ -4031,6 +4032,7 @@
3658502865, 3658502865,
2519048297, 2519048297,
1915965760, 1915965760,
1183846025 1183846025,
2713372123
] ]
} }

View File

@@ -53,15 +53,15 @@ class MiningMainnetTest(BitcoinTestFramework):
help='Block data file (default: %(default)s)', help='Block data file (default: %(default)s)',
) )
def mine(self, height, prev_hash, blocks, node, fees=0): def mine(self, height, prev_hash, blocks, node):
self.log.debug(f"height={height}") self.log.debug(f"height={height}")
block = CBlock() block = CBlock()
block.nVersion = 0x20000000 block.nVersion = 0x20000000
block.hashPrevBlock = int(prev_hash, 16) block.hashPrevBlock = int(prev_hash, 16)
block.nTime = blocks['timestamps'][height - 1] block.nTime = blocks['timestamps'][height - 1]
block.nBits = DIFF_1_N_BITS block.nBits = DIFF_1_N_BITS if height < 2016 else DIFF_4_N_BITS
block.nNonce = blocks['nonces'][height - 1] block.nNonce = blocks['nonces'][height - 1]
block.vtx = [create_coinbase(height=height, script_pubkey=bytes.fromhex(COINBASE_SCRIPT_PUBKEY), retarget_period=2016)] block.vtx = [create_coinbase(height=height, script_pubkey=bytes.fromhex(COINBASE_SCRIPT_PUBKEY), halving_period=210000)]
# The alternate mainnet chain was mined with non-timelocked coinbase txs. # The alternate mainnet chain was mined with non-timelocked coinbase txs.
block.vtx[0].nLockTime = 0 block.vtx[0].nLockTime = 0
block.vtx[0].vin[0].nSequence = SEQUENCE_FINAL block.vtx[0].vin[0].nSequence = SEQUENCE_FINAL
@@ -82,12 +82,15 @@ class MiningMainnetTest(BitcoinTestFramework):
self.log.info("Load alternative mainnet blocks") self.log.info("Load alternative mainnet blocks")
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), self.options.datafile) path = os.path.join(os.path.dirname(os.path.realpath(__file__)), self.options.datafile)
prev_hash = node.getbestblockhash() prev_hash = node.getbestblockhash()
blocks = None
with open(path, encoding='utf-8') as f: with open(path, encoding='utf-8') as f:
blocks = json.load(f) blocks = json.load(f)
n_blocks = len(blocks['timestamps']) n_blocks = len(blocks['timestamps'])
assert_equal(n_blocks, 2015) assert_equal(n_blocks, 2016)
for i in range(2015):
prev_hash = self.mine(i + 1, prev_hash, blocks, node) # Mine up to the last block of the first retarget period
for i in range(2015):
prev_hash = self.mine(i + 1, prev_hash, blocks, node)
assert_equal(node.getblockcount(), 2015) assert_equal(node.getblockcount(), 2015)
@@ -102,5 +105,9 @@ class MiningMainnetTest(BitcoinTestFramework):
assert_equal(mining_info['next']['bits'], nbits_str(DIFF_4_N_BITS)) assert_equal(mining_info['next']['bits'], nbits_str(DIFF_4_N_BITS))
assert_equal(mining_info['next']['target'], target_str(DIFF_4_TARGET)) assert_equal(mining_info['next']['target'], target_str(DIFF_4_TARGET))
# Mine first block of the second retarget period
height = 2016
prev_hash = self.mine(height, prev_hash, blocks, node)
assert_equal(node.getblockcount(), height)
if __name__ == '__main__': if __name__ == '__main__':
MiningMainnetTest(__file__).main() MiningMainnetTest(__file__).main()

View File

@@ -144,7 +144,7 @@ def script_BIP34_coinbase_height(height):
return CScript([CScriptNum(height)]) return CScript([CScriptNum(height)])
def create_coinbase(height, pubkey=None, *, script_pubkey=None, extra_output_script=None, fees=0, nValue=50, retarget_period=REGTEST_RETARGET_PERIOD): def create_coinbase(height, pubkey=None, *, script_pubkey=None, extra_output_script=None, fees=0, nValue=50, halving_period=REGTEST_RETARGET_PERIOD):
"""Create a coinbase transaction. """Create a coinbase transaction.
If pubkey is passed in, the coinbase output will be a P2PK output; If pubkey is passed in, the coinbase output will be a P2PK output;
@@ -158,7 +158,7 @@ def create_coinbase(height, pubkey=None, *, script_pubkey=None, extra_output_scr
coinbaseoutput = CTxOut() coinbaseoutput = CTxOut()
coinbaseoutput.nValue = nValue * COIN coinbaseoutput.nValue = nValue * COIN
if nValue == 50: if nValue == 50:
halvings = int(height / retarget_period) halvings = int(height / halving_period)
coinbaseoutput.nValue >>= halvings coinbaseoutput.nValue >>= halvings
coinbaseoutput.nValue += fees coinbaseoutput.nValue += fees
if pubkey is not None: if pubkey is not None: