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.
5 """Test the fundrawtransaction RPC."""
7 from test_framework
.test_framework
import BitcoinTestFramework
8 from test_framework
.util
import *
11 def get_unspent(listunspent
, amount
):
12 for utx
in listunspent
:
13 if utx
['amount'] == amount
:
15 raise AssertionError('Could not find unspent with amount={}'.format(amount
))
18 class RawTransactionsTest(BitcoinTestFramework
):
22 self
.setup_clean_chain
= True
25 def setup_network(self
, split
=False):
28 connect_nodes_bi(self
.nodes
, 0, 1)
29 connect_nodes_bi(self
.nodes
, 1, 2)
30 connect_nodes_bi(self
.nodes
, 0, 2)
31 connect_nodes_bi(self
.nodes
, 0, 3)
34 min_relay_tx_fee
= self
.nodes
[0].getnetworkinfo()['relayfee']
35 # This test is not meant to test fee estimation and we'd like
36 # to be sure all txs are sent at a consistent desired feerate
37 for node
in self
.nodes
:
38 node
.settxfee(min_relay_tx_fee
)
40 # if the fee's positive delta is higher than this value tests will fail,
41 # neg. delta always fail the tests.
42 # The size of the signature of every input may be at most 2 bytes larger
43 # than a minimum sized signature.
45 # = 2 bytes * minRelayTxFeePerByte
46 feeTolerance
= 2 * min_relay_tx_fee
/1000
48 self
.nodes
[2].generate(1)
50 self
.nodes
[0].generate(121)
53 # ensure that setting changePosition in fundraw with an exact match is handled properly
54 rawmatch
= self
.nodes
[2].createrawtransaction([], {self
.nodes
[2].getnewaddress():50})
55 rawmatch
= self
.nodes
[2].fundrawtransaction(rawmatch
, {"changePosition":1, "subtractFeeFromOutputs":[0]})
56 assert_equal(rawmatch
["changepos"], -1)
58 watchonly_address
= self
.nodes
[0].getnewaddress()
59 watchonly_pubkey
= self
.nodes
[0].validateaddress(watchonly_address
)["pubkey"]
60 watchonly_amount
= Decimal(200)
61 self
.nodes
[3].importpubkey(watchonly_pubkey
, "", True)
62 watchonly_txid
= self
.nodes
[0].sendtoaddress(watchonly_address
, watchonly_amount
)
63 self
.nodes
[0].sendtoaddress(self
.nodes
[3].getnewaddress(), watchonly_amount
/ 10)
65 self
.nodes
[0].sendtoaddress(self
.nodes
[2].getnewaddress(), 1.5)
66 self
.nodes
[0].sendtoaddress(self
.nodes
[2].getnewaddress(), 1.0)
67 self
.nodes
[0].sendtoaddress(self
.nodes
[2].getnewaddress(), 5.0)
69 self
.nodes
[0].generate(1)
76 outputs
= { self
.nodes
[0].getnewaddress() : 1.0 }
77 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
78 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
79 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
80 fee
= rawtxfund
['fee']
81 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
82 assert(len(dec_tx
['vin']) > 0) #test that we have enough inputs
84 ##############################
85 # simple test with two coins #
86 ##############################
88 outputs
= { self
.nodes
[0].getnewaddress() : 2.2 }
89 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
90 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
92 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
93 fee
= rawtxfund
['fee']
94 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
95 assert(len(dec_tx
['vin']) > 0) #test if we have enough inputs
97 ##############################
98 # simple test with two coins #
99 ##############################
101 outputs
= { self
.nodes
[0].getnewaddress() : 2.6 }
102 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
103 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
105 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
106 fee
= rawtxfund
['fee']
107 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
108 assert(len(dec_tx
['vin']) > 0)
109 assert_equal(dec_tx
['vin'][0]['scriptSig']['hex'], '')
112 ################################
113 # simple test with two outputs #
114 ################################
116 outputs
= { self
.nodes
[0].getnewaddress() : 2.6, self
.nodes
[1].getnewaddress() : 2.5 }
117 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
118 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
120 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
121 fee
= rawtxfund
['fee']
122 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
124 for out
in dec_tx
['vout']:
125 totalOut
+= out
['value']
127 assert(len(dec_tx
['vin']) > 0)
128 assert_equal(dec_tx
['vin'][0]['scriptSig']['hex'], '')
131 #########################################################################
132 # test a fundrawtransaction with a VIN greater than the required amount #
133 #########################################################################
134 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
136 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']}]
137 outputs
= { self
.nodes
[0].getnewaddress() : 1.0 }
138 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
139 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
140 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
142 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
143 fee
= rawtxfund
['fee']
144 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
146 for out
in dec_tx
['vout']:
147 totalOut
+= out
['value']
149 assert_equal(fee
+ totalOut
, utx
['amount']) #compare vin total and totalout+fee
152 #####################################################################
153 # test a fundrawtransaction with which will not get a change output #
154 #####################################################################
155 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
157 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']}]
158 outputs
= { self
.nodes
[0].getnewaddress() : Decimal(5.0) - fee
- feeTolerance
}
159 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
160 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
161 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
163 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
164 fee
= rawtxfund
['fee']
165 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
167 for out
in dec_tx
['vout']:
168 totalOut
+= out
['value']
170 assert_equal(rawtxfund
['changepos'], -1)
171 assert_equal(fee
+ totalOut
, utx
['amount']) #compare vin total and totalout+fee
174 ####################################################
175 # test a fundrawtransaction with an invalid option #
176 ####################################################
177 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
179 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']} ]
180 outputs
= { self
.nodes
[0].getnewaddress() : Decimal(4.0) }
181 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
182 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
183 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
185 assert_raises_jsonrpc(-3, "Unexpected key foo", self
.nodes
[2].fundrawtransaction
, rawtx
, {'foo':'bar'})
187 ############################################################
188 # test a fundrawtransaction with an invalid change address #
189 ############################################################
190 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
192 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']} ]
193 outputs
= { self
.nodes
[0].getnewaddress() : Decimal(4.0) }
194 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
195 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
196 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
198 assert_raises_jsonrpc(-5, "changeAddress must be a valid bitcoin address", self
.nodes
[2].fundrawtransaction
, rawtx
, {'changeAddress':'foobar'})
200 ############################################################
201 # test a fundrawtransaction with a provided change address #
202 ############################################################
203 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
205 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']} ]
206 outputs
= { self
.nodes
[0].getnewaddress() : Decimal(4.0) }
207 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
208 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
209 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
211 change
= self
.nodes
[2].getnewaddress()
212 assert_raises_jsonrpc(-8, "changePosition out of bounds", self
.nodes
[2].fundrawtransaction
, rawtx
, {'changeAddress':change
, 'changePosition':2})
213 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
, {'changeAddress': change
, 'changePosition': 0})
214 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
215 out
= dec_tx
['vout'][0]
216 assert_equal(change
, out
['scriptPubKey']['addresses'][0])
219 #########################################################################
220 # test a fundrawtransaction with a VIN smaller than the required amount #
221 #########################################################################
222 utx
= get_unspent(self
.nodes
[2].listunspent(), 1)
224 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']}]
225 outputs
= { self
.nodes
[0].getnewaddress() : 1.0 }
226 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
228 # 4-byte version + 1-byte vin count + 36-byte prevout then script_len
229 rawtx
= rawtx
[:82] + "0100" + rawtx
[84:]
231 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
232 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
233 assert_equal("00", dec_tx
['vin'][0]['scriptSig']['hex'])
235 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
236 fee
= rawtxfund
['fee']
237 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
240 for i
, out
in enumerate(dec_tx
['vout']):
241 totalOut
+= out
['value']
242 if out
['scriptPubKey']['addresses'][0] in outputs
:
245 assert_equal(i
, rawtxfund
['changepos'])
247 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
248 assert_equal("00", dec_tx
['vin'][0]['scriptSig']['hex'])
250 assert_equal(matchingOuts
, 1)
251 assert_equal(len(dec_tx
['vout']), 2)
254 ###########################################
255 # test a fundrawtransaction with two VINs #
256 ###########################################
257 utx
= get_unspent(self
.nodes
[2].listunspent(), 1)
258 utx2
= get_unspent(self
.nodes
[2].listunspent(), 5)
260 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']},{'txid' : utx2
['txid'], 'vout' : utx2
['vout']} ]
261 outputs
= { self
.nodes
[0].getnewaddress() : 6.0 }
262 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
263 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
264 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
266 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
267 fee
= rawtxfund
['fee']
268 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
271 for out
in dec_tx
['vout']:
272 totalOut
+= out
['value']
273 if out
['scriptPubKey']['addresses'][0] in outputs
:
276 assert_equal(matchingOuts
, 1)
277 assert_equal(len(dec_tx
['vout']), 2)
280 for vinOut
in dec_tx
['vin']:
282 if vinIn
['txid'] == vinOut
['txid']:
285 assert_equal(matchingIns
, 2) #we now must see two vins identical to vins given as params
287 #########################################################
288 # test a fundrawtransaction with two VINs and two vOUTs #
289 #########################################################
290 utx
= get_unspent(self
.nodes
[2].listunspent(), 1)
291 utx2
= get_unspent(self
.nodes
[2].listunspent(), 5)
293 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']},{'txid' : utx2
['txid'], 'vout' : utx2
['vout']} ]
294 outputs
= { self
.nodes
[0].getnewaddress() : 6.0, self
.nodes
[0].getnewaddress() : 1.0 }
295 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
296 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
297 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
299 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
300 fee
= rawtxfund
['fee']
301 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
304 for out
in dec_tx
['vout']:
305 totalOut
+= out
['value']
306 if out
['scriptPubKey']['addresses'][0] in outputs
:
309 assert_equal(matchingOuts
, 2)
310 assert_equal(len(dec_tx
['vout']), 3)
312 ##############################################
313 # test a fundrawtransaction with invalid vin #
314 ##############################################
315 listunspent
= self
.nodes
[2].listunspent()
316 inputs
= [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin!
317 outputs
= { self
.nodes
[0].getnewaddress() : 1.0}
318 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
319 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
321 assert_raises_jsonrpc(-4, "Insufficient funds", self
.nodes
[2].fundrawtransaction
, rawtx
)
323 ############################################################
324 #compare fee of a standard pubkeyhash transaction
326 outputs
= {self
.nodes
[1].getnewaddress():1.1}
327 rawtx
= self
.nodes
[0].createrawtransaction(inputs
, outputs
)
328 fundedTx
= self
.nodes
[0].fundrawtransaction(rawtx
)
330 #create same transaction over sendtoaddress
331 txId
= self
.nodes
[0].sendtoaddress(self
.nodes
[1].getnewaddress(), 1.1)
332 signedFee
= self
.nodes
[0].getrawmempool(True)[txId
]['fee']
335 feeDelta
= Decimal(fundedTx
['fee']) - Decimal(signedFee
)
336 assert(feeDelta
>= 0 and feeDelta
<= feeTolerance
)
337 ############################################################
339 ############################################################
340 #compare fee of a standard pubkeyhash transaction with multiple outputs
342 outputs
= {self
.nodes
[1].getnewaddress():1.1,self
.nodes
[1].getnewaddress():1.2,self
.nodes
[1].getnewaddress():0.1,self
.nodes
[1].getnewaddress():1.3,self
.nodes
[1].getnewaddress():0.2,self
.nodes
[1].getnewaddress():0.3}
343 rawtx
= self
.nodes
[0].createrawtransaction(inputs
, outputs
)
344 fundedTx
= self
.nodes
[0].fundrawtransaction(rawtx
)
345 #create same transaction over sendtoaddress
346 txId
= self
.nodes
[0].sendmany("", outputs
)
347 signedFee
= self
.nodes
[0].getrawmempool(True)[txId
]['fee']
350 feeDelta
= Decimal(fundedTx
['fee']) - Decimal(signedFee
)
351 assert(feeDelta
>= 0 and feeDelta
<= feeTolerance
)
352 ############################################################
355 ############################################################
356 #compare fee of a 2of2 multisig p2sh transaction
359 addr1
= self
.nodes
[1].getnewaddress()
360 addr2
= self
.nodes
[1].getnewaddress()
362 addr1Obj
= self
.nodes
[1].validateaddress(addr1
)
363 addr2Obj
= self
.nodes
[1].validateaddress(addr2
)
365 mSigObj
= self
.nodes
[1].addmultisigaddress(2, [addr1Obj
['pubkey'], addr2Obj
['pubkey']])
368 outputs
= {mSigObj
:1.1}
369 rawtx
= self
.nodes
[0].createrawtransaction(inputs
, outputs
)
370 fundedTx
= self
.nodes
[0].fundrawtransaction(rawtx
)
372 #create same transaction over sendtoaddress
373 txId
= self
.nodes
[0].sendtoaddress(mSigObj
, 1.1)
374 signedFee
= self
.nodes
[0].getrawmempool(True)[txId
]['fee']
377 feeDelta
= Decimal(fundedTx
['fee']) - Decimal(signedFee
)
378 assert(feeDelta
>= 0 and feeDelta
<= feeTolerance
)
379 ############################################################
382 ############################################################
383 #compare fee of a standard pubkeyhash transaction
386 addr1
= self
.nodes
[1].getnewaddress()
387 addr2
= self
.nodes
[1].getnewaddress()
388 addr3
= self
.nodes
[1].getnewaddress()
389 addr4
= self
.nodes
[1].getnewaddress()
390 addr5
= self
.nodes
[1].getnewaddress()
392 addr1Obj
= self
.nodes
[1].validateaddress(addr1
)
393 addr2Obj
= self
.nodes
[1].validateaddress(addr2
)
394 addr3Obj
= self
.nodes
[1].validateaddress(addr3
)
395 addr4Obj
= self
.nodes
[1].validateaddress(addr4
)
396 addr5Obj
= self
.nodes
[1].validateaddress(addr5
)
398 mSigObj
= self
.nodes
[1].addmultisigaddress(4, [addr1Obj
['pubkey'], addr2Obj
['pubkey'], addr3Obj
['pubkey'], addr4Obj
['pubkey'], addr5Obj
['pubkey']])
401 outputs
= {mSigObj
:1.1}
402 rawtx
= self
.nodes
[0].createrawtransaction(inputs
, outputs
)
403 fundedTx
= self
.nodes
[0].fundrawtransaction(rawtx
)
405 #create same transaction over sendtoaddress
406 txId
= self
.nodes
[0].sendtoaddress(mSigObj
, 1.1)
407 signedFee
= self
.nodes
[0].getrawmempool(True)[txId
]['fee']
410 feeDelta
= Decimal(fundedTx
['fee']) - Decimal(signedFee
)
411 assert(feeDelta
>= 0 and feeDelta
<= feeTolerance
)
412 ############################################################
415 ############################################################
416 # spend a 2of2 multisig transaction over fundraw
419 addr1
= self
.nodes
[2].getnewaddress()
420 addr2
= self
.nodes
[2].getnewaddress()
422 addr1Obj
= self
.nodes
[2].validateaddress(addr1
)
423 addr2Obj
= self
.nodes
[2].validateaddress(addr2
)
425 mSigObj
= self
.nodes
[2].addmultisigaddress(2, [addr1Obj
['pubkey'], addr2Obj
['pubkey']])
428 # send 1.2 BTC to msig addr
429 txId
= self
.nodes
[0].sendtoaddress(mSigObj
, 1.2)
431 self
.nodes
[1].generate(1)
434 oldBalance
= self
.nodes
[1].getbalance()
436 outputs
= {self
.nodes
[1].getnewaddress():1.1}
437 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
438 fundedTx
= self
.nodes
[2].fundrawtransaction(rawtx
)
440 signedTx
= self
.nodes
[2].signrawtransaction(fundedTx
['hex'])
441 txId
= self
.nodes
[2].sendrawtransaction(signedTx
['hex'])
443 self
.nodes
[1].generate(1)
446 # make sure funds are received at node1
447 assert_equal(oldBalance
+Decimal('1.10000000'), self
.nodes
[1].getbalance())
449 ############################################################
451 self
.nodes
[1].encryptwallet("test")
453 stop_node(self
.nodes
[0], 0)
454 stop_node(self
.nodes
[1], 2)
455 stop_node(self
.nodes
[2], 3)
457 self
.nodes
= start_nodes(self
.num_nodes
, self
.options
.tmpdir
)
458 # This test is not meant to test fee estimation and we'd like
459 # to be sure all txs are sent at a consistent desired feerate
460 for node
in self
.nodes
:
461 node
.settxfee(min_relay_tx_fee
)
463 connect_nodes_bi(self
.nodes
,0,1)
464 connect_nodes_bi(self
.nodes
,1,2)
465 connect_nodes_bi(self
.nodes
,0,2)
466 connect_nodes_bi(self
.nodes
,0,3)
470 self
.nodes
[1].getnewaddress()
471 self
.nodes
[1].getrawchangeaddress()
473 outputs
= {self
.nodes
[0].getnewaddress():1.1}
474 rawtx
= self
.nodes
[1].createrawtransaction(inputs
, outputs
)
475 # fund a transaction that requires a new key for the change output
476 # creating the key must be impossible because the wallet is locked
477 assert_raises_jsonrpc(-4, "Keypool ran out, please call keypoolrefill first", self
.nodes
[1].fundrawtransaction
, rawtx
)
480 self
.nodes
[1].walletpassphrase("test", 100)
481 self
.nodes
[1].keypoolrefill(8) #need to refill the keypool to get an internal change address
482 self
.nodes
[1].walletlock()
484 assert_raises_jsonrpc(-13, "walletpassphrase", self
.nodes
[1].sendtoaddress
, self
.nodes
[0].getnewaddress(), 1.2)
486 oldBalance
= self
.nodes
[0].getbalance()
489 outputs
= {self
.nodes
[0].getnewaddress():1.1}
490 rawtx
= self
.nodes
[1].createrawtransaction(inputs
, outputs
)
491 fundedTx
= self
.nodes
[1].fundrawtransaction(rawtx
)
493 #now we need to unlock
494 self
.nodes
[1].walletpassphrase("test", 600)
495 signedTx
= self
.nodes
[1].signrawtransaction(fundedTx
['hex'])
496 txId
= self
.nodes
[1].sendrawtransaction(signedTx
['hex'])
497 self
.nodes
[1].generate(1)
500 # make sure funds are received at node1
501 assert_equal(oldBalance
+Decimal('51.10000000'), self
.nodes
[0].getbalance())
504 ###############################################
505 # multiple (~19) inputs tx test | Compare fee #
506 ###############################################
508 #empty node1, send some small coins from node0 to node1
509 self
.nodes
[1].sendtoaddress(self
.nodes
[0].getnewaddress(), self
.nodes
[1].getbalance(), "", "", True)
511 self
.nodes
[0].generate(1)
514 for i
in range(0,20):
515 self
.nodes
[0].sendtoaddress(self
.nodes
[1].getnewaddress(), 0.01)
516 self
.nodes
[0].generate(1)
519 #fund a tx with ~20 small inputs
521 outputs
= {self
.nodes
[0].getnewaddress():0.15,self
.nodes
[0].getnewaddress():0.04}
522 rawtx
= self
.nodes
[1].createrawtransaction(inputs
, outputs
)
523 fundedTx
= self
.nodes
[1].fundrawtransaction(rawtx
)
525 #create same transaction over sendtoaddress
526 txId
= self
.nodes
[1].sendmany("", outputs
)
527 signedFee
= self
.nodes
[1].getrawmempool(True)[txId
]['fee']
530 feeDelta
= Decimal(fundedTx
['fee']) - Decimal(signedFee
)
531 assert(feeDelta
>= 0 and feeDelta
<= feeTolerance
*19) #~19 inputs
534 #############################################
535 # multiple (~19) inputs tx test | sign/send #
536 #############################################
538 #again, empty node1, send some small coins from node0 to node1
539 self
.nodes
[1].sendtoaddress(self
.nodes
[0].getnewaddress(), self
.nodes
[1].getbalance(), "", "", True)
541 self
.nodes
[0].generate(1)
544 for i
in range(0,20):
545 self
.nodes
[0].sendtoaddress(self
.nodes
[1].getnewaddress(), 0.01)
546 self
.nodes
[0].generate(1)
549 #fund a tx with ~20 small inputs
550 oldBalance
= self
.nodes
[0].getbalance()
553 outputs
= {self
.nodes
[0].getnewaddress():0.15,self
.nodes
[0].getnewaddress():0.04}
554 rawtx
= self
.nodes
[1].createrawtransaction(inputs
, outputs
)
555 fundedTx
= self
.nodes
[1].fundrawtransaction(rawtx
)
556 fundedAndSignedTx
= self
.nodes
[1].signrawtransaction(fundedTx
['hex'])
557 txId
= self
.nodes
[1].sendrawtransaction(fundedAndSignedTx
['hex'])
559 self
.nodes
[0].generate(1)
561 assert_equal(oldBalance
+Decimal('50.19000000'), self
.nodes
[0].getbalance()) #0.19+block reward
563 #####################################################
564 # test fundrawtransaction with OP_RETURN and no vin #
565 #####################################################
567 rawtx
= "0100000000010000000000000000066a047465737400000000"
568 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
570 assert_equal(len(dec_tx
['vin']), 0)
571 assert_equal(len(dec_tx
['vout']), 1)
573 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
574 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
576 assert_greater_than(len(dec_tx
['vin']), 0) # at least one vin
577 assert_equal(len(dec_tx
['vout']), 2) # one change output added
580 ##################################################
581 # test a fundrawtransaction using only watchonly #
582 ##################################################
585 outputs
= {self
.nodes
[2].getnewaddress() : watchonly_amount
/ 2}
586 rawtx
= self
.nodes
[3].createrawtransaction(inputs
, outputs
)
588 result
= self
.nodes
[3].fundrawtransaction(rawtx
, {'includeWatching': True })
589 res_dec
= self
.nodes
[0].decoderawtransaction(result
["hex"])
590 assert_equal(len(res_dec
["vin"]), 1)
591 assert_equal(res_dec
["vin"][0]["txid"], watchonly_txid
)
593 assert("fee" in result
.keys())
594 assert_greater_than(result
["changepos"], -1)
596 ###############################################################
597 # test fundrawtransaction using the entirety of watched funds #
598 ###############################################################
601 outputs
= {self
.nodes
[2].getnewaddress() : watchonly_amount
}
602 rawtx
= self
.nodes
[3].createrawtransaction(inputs
, outputs
)
604 # Backward compatibility test (2nd param is includeWatching)
605 result
= self
.nodes
[3].fundrawtransaction(rawtx
, True)
606 res_dec
= self
.nodes
[0].decoderawtransaction(result
["hex"])
607 assert_equal(len(res_dec
["vin"]), 2)
608 assert(res_dec
["vin"][0]["txid"] == watchonly_txid
or res_dec
["vin"][1]["txid"] == watchonly_txid
)
610 assert_greater_than(result
["fee"], 0)
611 assert_greater_than(result
["changepos"], -1)
612 assert_equal(result
["fee"] + res_dec
["vout"][result
["changepos"]]["value"], watchonly_amount
/ 10)
614 signedtx
= self
.nodes
[3].signrawtransaction(result
["hex"])
615 assert(not signedtx
["complete"])
616 signedtx
= self
.nodes
[0].signrawtransaction(signedtx
["hex"])
617 assert(signedtx
["complete"])
618 self
.nodes
[0].sendrawtransaction(signedtx
["hex"])
619 self
.nodes
[0].generate(1)
622 #######################
623 # Test feeRate option #
624 #######################
626 # Make sure there is exactly one input so coin selection can't skew the result
627 assert_equal(len(self
.nodes
[3].listunspent(1)), 1)
630 outputs
= {self
.nodes
[3].getnewaddress() : 1}
631 rawtx
= self
.nodes
[3].createrawtransaction(inputs
, outputs
)
632 result
= self
.nodes
[3].fundrawtransaction(rawtx
) # uses min_relay_tx_fee (set by settxfee)
633 result2
= self
.nodes
[3].fundrawtransaction(rawtx
, {"feeRate": 2*min_relay_tx_fee
})
634 result3
= self
.nodes
[3].fundrawtransaction(rawtx
, {"feeRate": 10*min_relay_tx_fee
})
635 result_fee_rate
= result
['fee'] * 1000 / count_bytes(result
['hex'])
636 assert_fee_amount(result2
['fee'], count_bytes(result2
['hex']), 2 * result_fee_rate
)
637 assert_fee_amount(result3
['fee'], count_bytes(result3
['hex']), 10 * result_fee_rate
)
639 #############################
640 # Test address reuse option #
641 #############################
643 result3
= self
.nodes
[3].fundrawtransaction(rawtx
, {"reserveChangeKey": False})
644 res_dec
= self
.nodes
[0].decoderawtransaction(result3
["hex"])
646 for out
in res_dec
['vout']:
647 if out
['value'] > 1.0:
648 changeaddress
+= out
['scriptPubKey']['addresses'][0]
649 assert(changeaddress
!= "")
650 nextaddr
= self
.nodes
[3].getrawchangeaddress()
651 # frt should not have removed the key from the keypool
652 assert(changeaddress
== nextaddr
)
654 result3
= self
.nodes
[3].fundrawtransaction(rawtx
)
655 res_dec
= self
.nodes
[0].decoderawtransaction(result3
["hex"])
657 for out
in res_dec
['vout']:
658 if out
['value'] > 1.0:
659 changeaddress
+= out
['scriptPubKey']['addresses'][0]
660 assert(changeaddress
!= "")
661 nextaddr
= self
.nodes
[3].getnewaddress()
662 # Now the change address key should be removed from the keypool
663 assert(changeaddress
!= nextaddr
)
665 ######################################
666 # Test subtractFeeFromOutputs option #
667 ######################################
669 # Make sure there is exactly one input so coin selection can't skew the result
670 assert_equal(len(self
.nodes
[3].listunspent(1)), 1)
673 outputs
= {self
.nodes
[2].getnewaddress(): 1}
674 rawtx
= self
.nodes
[3].createrawtransaction(inputs
, outputs
)
676 result
= [self
.nodes
[3].fundrawtransaction(rawtx
), # uses min_relay_tx_fee (set by settxfee)
677 self
.nodes
[3].fundrawtransaction(rawtx
, {"subtractFeeFromOutputs": []}), # empty subtraction list
678 self
.nodes
[3].fundrawtransaction(rawtx
, {"subtractFeeFromOutputs": [0]}), # uses min_relay_tx_fee (set by settxfee)
679 self
.nodes
[3].fundrawtransaction(rawtx
, {"feeRate": 2*min_relay_tx_fee
}),
680 self
.nodes
[3].fundrawtransaction(rawtx
, {"feeRate": 2*min_relay_tx_fee
, "subtractFeeFromOutputs": [0]})]
682 dec_tx
= [self
.nodes
[3].decoderawtransaction(tx
['hex']) for tx
in result
]
683 output
= [d
['vout'][1 - r
['changepos']]['value'] for d
, r
in zip(dec_tx
, result
)]
684 change
= [d
['vout'][r
['changepos']]['value'] for d
, r
in zip(dec_tx
, result
)]
686 assert_equal(result
[0]['fee'], result
[1]['fee'], result
[2]['fee'])
687 assert_equal(result
[3]['fee'], result
[4]['fee'])
688 assert_equal(change
[0], change
[1])
689 assert_equal(output
[0], output
[1])
690 assert_equal(output
[0], output
[2] + result
[2]['fee'])
691 assert_equal(change
[0] + result
[0]['fee'], change
[2])
692 assert_equal(output
[3], output
[4] + result
[4]['fee'])
693 assert_equal(change
[3] + result
[3]['fee'], change
[4])
696 outputs
= {self
.nodes
[2].getnewaddress(): value
for value
in (1.0, 1.1, 1.2, 1.3)}
697 rawtx
= self
.nodes
[3].createrawtransaction(inputs
, outputs
)
699 result
= [self
.nodes
[3].fundrawtransaction(rawtx
),
700 # split the fee between outputs 0, 2, and 3, but not output 1
701 self
.nodes
[3].fundrawtransaction(rawtx
, {"subtractFeeFromOutputs": [0, 2, 3]})]
703 dec_tx
= [self
.nodes
[3].decoderawtransaction(result
[0]['hex']),
704 self
.nodes
[3].decoderawtransaction(result
[1]['hex'])]
706 # Nested list of non-change output amounts for each transaction
707 output
= [[out
['value'] for i
, out
in enumerate(d
['vout']) if i
!= r
['changepos']]
708 for d
, r
in zip(dec_tx
, result
)]
710 # List of differences in output amounts between normal and subtractFee transactions
711 share
= [o0
- o1
for o0
, o1
in zip(output
[0], output
[1])]
713 # output 1 is the same in both transactions
714 assert_equal(share
[1], 0)
716 # the other 3 outputs are smaller as a result of subtractFeeFromOutputs
717 assert_greater_than(share
[0], 0)
718 assert_greater_than(share
[2], 0)
719 assert_greater_than(share
[3], 0)
721 # outputs 2 and 3 take the same share of the fee
722 assert_equal(share
[2], share
[3])
724 # output 0 takes at least as much share of the fee, and no more than 2 satoshis more, than outputs 2 and 3
725 assert_greater_than_or_equal(share
[0], share
[2])
726 assert_greater_than_or_equal(share
[2] + Decimal(2e-8), share
[0])
728 # the fee is the same in both transactions
729 assert_equal(result
[0]['fee'], result
[1]['fee'])
731 # the total subtracted from the outputs is equal to the fee
732 assert_equal(share
[0] + share
[2] + share
[3], result
[0]['fee'])
734 if __name__
== '__main__':
735 RawTransactionsTest().main()