forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathmining_mainnet.py
executable file
·105 lines (86 loc) · 3.52 KB
/
mining_mainnet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/env python3
# Copyright (c) 2025 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test mining on an alternate mainnet
Test mining related RPCs that involve difficulty adjustment, which
regtest doesn't have.
It uses an alternate mainnet chain. See data/README.md for how it was generated.
Mine one retarget period worth of blocks with a short interval in
order to maximally raise the difficulty. Verify this using the getmininginfo RPC.
"""
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
)
from test_framework.blocktools import (
DIFF_1_N_BITS,
DIFF_1_TARGET,
DIFF_4_N_BITS,
DIFF_4_TARGET,
create_coinbase,
nbits_str,
target_str
)
from test_framework.messages import (
CBlock,
)
import json
import os
# See data/README.md
COINBASE_SCRIPT_PUBKEY="76a914eadbac7f36c37e39361168b7aaee3cb24a25312d88ac"
class MiningMainnetTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
self.chain = "" # main
def add_options(self, parser):
parser.add_argument(
'--datafile',
default='data/mainnet_alt.json',
help='Block data file (default: %(default)s)',
)
self.add_wallet_options(parser)
def mine(self, height, prev_hash, blocks, node, fees=0):
self.log.debug(f"height={height}")
block = CBlock()
block.nVersion = 0x20000000
block.hashPrevBlock = int(prev_hash, 16)
block.nTime = blocks['timestamps'][height - 1]
block.nBits = DIFF_1_N_BITS
block.nNonce = blocks['nonces'][height - 1]
block.vtx = [create_coinbase(height=height, script_pubkey=bytes.fromhex(COINBASE_SCRIPT_PUBKEY), retarget_period=2016)]
block.hashMerkleRoot = block.calc_merkle_root()
block.rehash()
block_hex = block.serialize(with_witness=False).hex()
self.log.debug(block_hex)
assert_equal(node.submitblock(block_hex), None)
prev_hash = node.getbestblockhash()
assert_equal(prev_hash, block.hash)
return prev_hash
def run_test(self):
node = self.nodes[0]
# Clear disk space warning
node.stderr.seek(0)
node.stderr.truncate()
self.log.info("Load alternative mainnet blocks")
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), self.options.datafile)
prev_hash = node.getbestblockhash()
with open(path, encoding='utf-8') as f:
blocks = json.load(f)
n_blocks = len(blocks['timestamps'])
assert_equal(n_blocks, 2015)
for i in range(2015):
prev_hash = self.mine(i + 1, prev_hash, blocks, node)
assert_equal(node.getblockcount(), 2015)
self.log.info("Check difficulty adjustment with getmininginfo")
mining_info = node.getmininginfo()
assert_equal(mining_info['difficulty'], 1)
assert_equal(mining_info['bits'], nbits_str(DIFF_1_N_BITS))
assert_equal(mining_info['target'], target_str(DIFF_1_TARGET))
assert_equal(mining_info['next']['height'], 2016)
assert_equal(mining_info['next']['difficulty'], 4)
assert_equal(mining_info['next']['bits'], nbits_str(DIFF_4_N_BITS))
assert_equal(mining_info['next']['target'], target_str(DIFF_4_TARGET))
if __name__ == '__main__':
MiningMainnetTest(__file__).main()