mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-02 14:37:42 -03:00
105 lines
3.5 KiB
Python
Executable file
105 lines
3.5 KiB
Python
Executable file
#!/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()
|