|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# Copyright (c) 2014-2018 The Bitcoin Core developers |
| 3 | +# Distributed under the MIT software license, see the accompanying |
| 4 | +# file COPYING or http://www.opensource.org/licenses/mit-license.php. |
| 5 | +"""Test mining RPCs |
| 6 | +
|
| 7 | +- getmininginfo |
| 8 | +- getblocktemplate proposal mode |
| 9 | +- submitblock""" |
| 10 | + |
| 11 | +from binascii import b2a_hex |
| 12 | + |
| 13 | +from test_framework.blocktools import create_coinbase |
| 14 | +from test_framework.messages import CBlock |
| 15 | +from test_framework.test_framework import BitcoinTestFramework |
| 16 | +from test_framework.util import assert_equal, assert_raises_rpc_error |
| 17 | + |
| 18 | +mandatory_privkey = "cNaQCDwmmh4dS9LzCgVtyy1e1xjCJ21GUDHe9K98nzb689JvinGV" |
| 19 | +mandatory_address = "n3NkSZqoPMCQN5FENxUBw4qVATbytH6FDK" |
| 20 | +mandatory_pubkey = "02fcba7ecf41bc7e1be4ee122d9d22e3333671eb0a3a87b5cdf099d59874e1940f" |
| 21 | +mandatory_script = "76a914efc58b838b3153174bf3d1677b7213353a4dccfd88ac" |
| 22 | + |
| 23 | +def b2x(b): |
| 24 | + return b2a_hex(b).decode('ascii') |
| 25 | + |
| 26 | +def assert_template(node, block, expect, rehash=True): |
| 27 | + if rehash: |
| 28 | + block.hashMerkleRoot = block.calc_merkle_root() |
| 29 | + rsp = node.getblocktemplate({'data': b2x(block.serialize()), 'mode': 'proposal'}) |
| 30 | + assert_equal(rsp, expect) |
| 31 | + |
| 32 | +class MandatoryCoinbaseTest(BitcoinTestFramework): |
| 33 | + def set_test_params(self): |
| 34 | + self.num_nodes = 2 |
| 35 | + self.setup_clean_chain = True |
| 36 | + # Non-zero coinbase outputs *must* match this. Not setting it means anything is allowed |
| 37 | + self.extra_args = [["-con_mandatorycoinbase="+mandatory_script], []] |
| 38 | + |
| 39 | + def run_test(self): |
| 40 | + node0 = self.nodes[0] |
| 41 | + node1 = self.nodes[1] |
| 42 | + |
| 43 | + node0.importprivkey(mandatory_privkey) |
| 44 | + |
| 45 | + self.log.info("generatetoaddress: Making blocks of various kinds, checking for rejection") |
| 46 | + |
| 47 | + # Create valid blocks to get out of IBD and get some funds (subsidy goes to permitted addr) |
| 48 | + node0.generatetoaddress(101, mandatory_address) |
| 49 | + |
| 50 | + # Generating for another address will not work |
| 51 | + assert_raises_rpc_error(-1, "CreateNewBlock: TestBlockValidity failed: bad-coinbase-txos", node0.generatetoaddress, 1, node0.getnewaddress()) |
| 52 | + |
| 53 | + # Have non-mandatory node make a template |
| 54 | + self.sync_all() |
| 55 | + tmpl = node1.getblocktemplate() |
| 56 | + |
| 57 | + # We make a block with OP_TRUE coinbase output that will fail on node0 |
| 58 | + coinbase_tx = create_coinbase(height=int(tmpl["height"]) + 1) |
| 59 | + # sequence numbers must not be max for nLockTime to have effect |
| 60 | + coinbase_tx.vin[0].nSequence = 2 ** 32 - 2 |
| 61 | + coinbase_tx.rehash() |
| 62 | + |
| 63 | + block = CBlock() |
| 64 | + block.nVersion = tmpl["version"] |
| 65 | + block.hashPrevBlock = int(tmpl["previousblockhash"], 16) |
| 66 | + block.nTime = tmpl["curtime"] |
| 67 | + block.nBits = int(tmpl["bits"], 16) |
| 68 | + block.nNonce = 0 |
| 69 | + block.vtx = [coinbase_tx] |
| 70 | + |
| 71 | + self.log.info("getblocktemplate: Test block on both nodes") |
| 72 | + assert_equal(node0.submitblock(b2x(block.serialize())), 'invalid') |
| 73 | + assert_template(node1, block, None) |
| 74 | + |
| 75 | + self.log.info("getblocktemplate: Test non-subsidy block on both nodes") |
| 76 | + # Without block reward anything goes, this allows commitment outputs like segwit |
| 77 | + coinbase_tx.vout[0].nValue = 0 |
| 78 | + coinbase_tx.rehash() |
| 79 | + block.vtx = [coinbase_tx] |
| 80 | + assert_template(node0, block, None) |
| 81 | + assert_template(node1, block, None) |
| 82 | + |
| 83 | +if __name__ == '__main__': |
| 84 | + MandatoryCoinbaseTest().main() |
0 commit comments