[CoinControl] Allow non-wallet owned change addresses
[bitcoinplatinum.git] / qa / rpc-tests / getblocktemplate_proposals.py
blob7a4f8f8fdc3c2a3cc50e3c71030c3578d3919c1e
1 #!/usr/bin/env python3
2 # Copyright (c) 2014-2016 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.
6 from test_framework.test_framework import BitcoinTestFramework
7 from test_framework.util import *
9 from binascii import a2b_hex, b2a_hex
10 from hashlib import sha256
11 from struct import pack
13 def b2x(b):
14 return b2a_hex(b).decode('ascii')
16 # NOTE: This does not work for signed numbers (set the high bit) or zero (use b'\0')
17 def encodeUNum(n):
18 s = bytearray(b'\1')
19 while n > 127:
20 s[0] += 1
21 s.append(n % 256)
22 n //= 256
23 s.append(n)
24 return bytes(s)
26 def varlenEncode(n):
27 if n < 0xfd:
28 return pack('<B', n)
29 if n <= 0xffff:
30 return b'\xfd' + pack('<H', n)
31 if n <= 0xffffffff:
32 return b'\xfe' + pack('<L', n)
33 return b'\xff' + pack('<Q', n)
35 def dblsha(b):
36 return sha256(sha256(b).digest()).digest()
38 def genmrklroot(leaflist):
39 cur = leaflist
40 while len(cur) > 1:
41 n = []
42 if len(cur) & 1:
43 cur.append(cur[-1])
44 for i in range(0, len(cur), 2):
45 n.append(dblsha(cur[i] + cur[i+1]))
46 cur = n
47 return cur[0]
49 def template_to_bytearray(tmpl, txlist):
50 blkver = pack('<L', tmpl['version'])
51 mrklroot = genmrklroot(list(dblsha(a) for a in txlist))
52 timestamp = pack('<L', tmpl['curtime'])
53 nonce = b'\0\0\0\0'
54 blk = blkver + a2b_hex(tmpl['previousblockhash'])[::-1] + mrklroot + timestamp + a2b_hex(tmpl['bits'])[::-1] + nonce
55 blk += varlenEncode(len(txlist))
56 for tx in txlist:
57 blk += tx
58 return bytearray(blk)
60 def template_to_hex(tmpl, txlist):
61 return b2x(template_to_bytearray(tmpl, txlist))
63 def assert_template(node, tmpl, txlist, expect):
64 rsp = node.getblocktemplate({'data':template_to_hex(tmpl, txlist),'mode':'proposal'})
65 if rsp != expect:
66 raise AssertionError('unexpected: %s' % (rsp,))
68 class GetBlockTemplateProposalTest(BitcoinTestFramework):
69 '''
70 Test block proposals with getblocktemplate.
71 '''
73 def __init__(self):
74 super().__init__()
75 self.num_nodes = 2
76 self.setup_clean_chain = False
78 def setup_network(self):
79 self.nodes = self.setup_nodes()
80 connect_nodes_bi(self.nodes, 0, 1)
82 def run_test(self):
83 node = self.nodes[0]
84 node.generate(1) # Mine a block to leave initial block download
85 tmpl = node.getblocktemplate()
86 if 'coinbasetxn' not in tmpl:
87 rawcoinbase = encodeUNum(tmpl['height'])
88 rawcoinbase += b'\x01-'
89 hexcoinbase = b2x(rawcoinbase)
90 hexoutval = b2x(pack('<Q', tmpl['coinbasevalue']))
91 tmpl['coinbasetxn'] = {'data': '01000000' + '01' + '0000000000000000000000000000000000000000000000000000000000000000ffffffff' + ('%02x' % (len(rawcoinbase),)) + hexcoinbase + 'fffffffe' + '01' + hexoutval + '00' + '00000000'}
92 txlist = list(bytearray(a2b_hex(a['data'])) for a in (tmpl['coinbasetxn'],) + tuple(tmpl['transactions']))
94 # Test 0: Capability advertised
95 assert('proposal' in tmpl['capabilities'])
97 # NOTE: This test currently FAILS (regtest mode doesn't enforce block height in coinbase)
98 ## Test 1: Bad height in coinbase
99 #txlist[0][4+1+36+1+1] += 1
100 #assert_template(node, tmpl, txlist, 'FIXME')
101 #txlist[0][4+1+36+1+1] -= 1
103 # Test 2: Bad input hash for gen tx
104 txlist[0][4+1] += 1
105 assert_template(node, tmpl, txlist, 'bad-cb-missing')
106 txlist[0][4+1] -= 1
108 # Test 3: Truncated final tx
109 lastbyte = txlist[-1].pop()
110 assert_raises(JSONRPCException, assert_template, node, tmpl, txlist, 'n/a')
111 txlist[-1].append(lastbyte)
113 # Test 4: Add an invalid tx to the end (duplicate of gen tx)
114 txlist.append(txlist[0])
115 assert_template(node, tmpl, txlist, 'bad-txns-duplicate')
116 txlist.pop()
118 # Test 5: Add an invalid tx to the end (non-duplicate)
119 txlist.append(bytearray(txlist[0]))
120 txlist[-1][4+1] = 0xff
121 assert_template(node, tmpl, txlist, 'bad-txns-inputs-missingorspent')
122 txlist.pop()
124 # Test 6: Future tx lock time
125 txlist[0][-4:] = b'\xff\xff\xff\xff'
126 assert_template(node, tmpl, txlist, 'bad-txns-nonfinal')
127 txlist[0][-4:] = b'\0\0\0\0'
129 # Test 7: Bad tx count
130 txlist.append(b'')
131 assert_raises(JSONRPCException, assert_template, node, tmpl, txlist, 'n/a')
132 txlist.pop()
134 # Test 8: Bad bits
135 realbits = tmpl['bits']
136 tmpl['bits'] = '1c0000ff' # impossible in the real world
137 assert_template(node, tmpl, txlist, 'bad-diffbits')
138 tmpl['bits'] = realbits
140 # Test 9: Bad merkle root
141 rawtmpl = template_to_bytearray(tmpl, txlist)
142 rawtmpl[4+32] = (rawtmpl[4+32] + 1) % 0x100
143 rsp = node.getblocktemplate({'data':b2x(rawtmpl),'mode':'proposal'})
144 if rsp != 'bad-txnmrklroot':
145 raise AssertionError('unexpected: %s' % (rsp,))
147 # Test 10: Bad timestamps
148 realtime = tmpl['curtime']
149 tmpl['curtime'] = 0x7fffffff
150 assert_template(node, tmpl, txlist, 'time-too-new')
151 tmpl['curtime'] = 0
152 assert_template(node, tmpl, txlist, 'time-too-old')
153 tmpl['curtime'] = realtime
155 # Test 11: Valid block
156 assert_template(node, tmpl, txlist, None)
158 # Test 12: Orphan block
159 tmpl['previousblockhash'] = 'ff00' * 16
160 assert_template(node, tmpl, txlist, 'inconclusive-not-best-prevblk')
162 if __name__ == '__main__':
163 GetBlockTemplateProposalTest().main()