Skip to content

Commit 5d77f54

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

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed

test/functional/mandatory_coinbase.py

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

0 commit comments

Comments
 (0)