Skip to content

Commit a5536b4

Browse files
committed
add mandatory coinbase functional test
1 parent 63cee78 commit a5536b4

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

Diff for: test/functional/mandatory_coinbase.py

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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

Comments
 (0)