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
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')
30 return b
'\xfd' + pack('<H', n
)
32 return b
'\xfe' + pack('<L', n
)
33 return b
'\xff' + pack('<Q', n
)
36 return sha256(sha256(b
).digest()).digest()
38 def genmrklroot(leaflist
):
44 for i
in range(0, len(cur
), 2):
45 n
.append(dblsha(cur
[i
] + cur
[i
+1]))
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'])
54 blk
= blkver
+ a2b_hex(tmpl
['previousblockhash'])[::-1] + mrklroot
+ timestamp
+ a2b_hex(tmpl
['bits'])[::-1] + nonce
55 blk
+= varlenEncode(len(txlist
))
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'})
66 raise AssertionError('unexpected: %s' % (rsp
,))
68 class GetBlockTemplateProposalTest(BitcoinTestFramework
):
70 Test block proposals with getblocktemplate.
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)
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
105 assert_template(node
, tmpl
, txlist
, 'bad-cb-missing')
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')
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')
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
131 assert_raises(JSONRPCException
, assert_template
, node
, tmpl
, txlist
, 'n/a')
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')
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()