Skip to content

Commit 22396a7

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

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

Diff for: test/functional/mandatory_coinbase.py

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

0 commit comments

Comments
 (0)