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
))
17 class RawTransactionsTest(BitcoinTestFramework
):
18 def set_test_params(self
):
20 self
.setup_clean_chain
= True
22 def setup_network(self
, split
=False):
25 connect_nodes_bi(self
.nodes
, 0, 1)
26 connect_nodes_bi(self
.nodes
, 1, 2)
27 connect_nodes_bi(self
.nodes
, 0, 2)
28 connect_nodes_bi(self
.nodes
, 0, 3)
31 min_relay_tx_fee
= self
.nodes
[0].getnetworkinfo()['relayfee']
32 # This test is not meant to test fee estimation and we'd like
33 # to be sure all txs are sent at a consistent desired feerate
34 for node
in self
.nodes
:
35 node
.settxfee(min_relay_tx_fee
)
37 # if the fee's positive delta is higher than this value tests will fail,
38 # neg. delta always fail the tests.
39 # The size of the signature of every input may be at most 2 bytes larger
40 # than a minimum sized signature.
42 # = 2 bytes * minRelayTxFeePerByte
43 feeTolerance
= 2 * min_relay_tx_fee
/1000
45 self
.nodes
[2].generate(1)
47 self
.nodes
[0].generate(121)
50 # ensure that setting changePosition in fundraw with an exact match is handled properly
51 rawmatch
= self
.nodes
[2].createrawtransaction([], {self
.nodes
[2].getnewaddress():50})
52 rawmatch
= self
.nodes
[2].fundrawtransaction(rawmatch
, {"changePosition":1, "subtractFeeFromOutputs":[0]})
53 assert_equal(rawmatch
["changepos"], -1)
55 watchonly_address
= self
.nodes
[0].getnewaddress()
56 watchonly_pubkey
= self
.nodes
[0].validateaddress(watchonly_address
)["pubkey"]
57 watchonly_amount
= Decimal(200)
58 self
.nodes
[3].importpubkey(watchonly_pubkey
, "", True)
59 watchonly_txid
= self
.nodes
[0].sendtoaddress(watchonly_address
, watchonly_amount
)
60 self
.nodes
[0].sendtoaddress(self
.nodes
[3].getnewaddress(), watchonly_amount
/ 10)
62 self
.nodes
[0].sendtoaddress(self
.nodes
[2].getnewaddress(), 1.5)
63 self
.nodes
[0].sendtoaddress(self
.nodes
[2].getnewaddress(), 1.0)
64 self
.nodes
[0].sendtoaddress(self
.nodes
[2].getnewaddress(), 5.0)
66 self
.nodes
[0].generate(1)
73 outputs
= { self
.nodes
[0].getnewaddress() : 1.0 }
74 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
75 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
76 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
77 fee
= rawtxfund
['fee']
78 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
79 assert(len(dec_tx
['vin']) > 0) #test that we have enough inputs
81 ##############################
82 # simple test with two coins #
83 ##############################
85 outputs
= { self
.nodes
[0].getnewaddress() : 2.2 }
86 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
87 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
89 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
90 fee
= rawtxfund
['fee']
91 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
92 assert(len(dec_tx
['vin']) > 0) #test if we have enough inputs
94 ##############################
95 # simple test with two coins #
96 ##############################
98 outputs
= { self
.nodes
[0].getnewaddress() : 2.6 }
99 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
100 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
102 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
103 fee
= rawtxfund
['fee']
104 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
105 assert(len(dec_tx
['vin']) > 0)
106 assert_equal(dec_tx
['vin'][0]['scriptSig']['hex'], '')
109 ################################
110 # simple test with two outputs #
111 ################################
113 outputs
= { self
.nodes
[0].getnewaddress() : 2.6, self
.nodes
[1].getnewaddress() : 2.5 }
114 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
115 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
117 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
118 fee
= rawtxfund
['fee']
119 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
121 for out
in dec_tx
['vout']:
122 totalOut
+= out
['value']
124 assert(len(dec_tx
['vin']) > 0)
125 assert_equal(dec_tx
['vin'][0]['scriptSig']['hex'], '')
128 #########################################################################
129 # test a fundrawtransaction with a VIN greater than the required amount #
130 #########################################################################
131 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
133 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']}]
134 outputs
= { self
.nodes
[0].getnewaddress() : 1.0 }
135 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
136 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
137 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
139 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
140 fee
= rawtxfund
['fee']
141 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
143 for out
in dec_tx
['vout']:
144 totalOut
+= out
['value']
146 assert_equal(fee
+ totalOut
, utx
['amount']) #compare vin total and totalout+fee
149 #####################################################################
150 # test a fundrawtransaction with which will not get a change output #
151 #####################################################################
152 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
154 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']}]
155 outputs
= { self
.nodes
[0].getnewaddress() : Decimal(5.0) - fee
- feeTolerance
}
156 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
157 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
158 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
160 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
161 fee
= rawtxfund
['fee']
162 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
164 for out
in dec_tx
['vout']:
165 totalOut
+= out
['value']
167 assert_equal(rawtxfund
['changepos'], -1)
168 assert_equal(fee
+ totalOut
, utx
['amount']) #compare vin total and totalout+fee
171 ####################################################
172 # test a fundrawtransaction with an invalid option #
173 ####################################################
174 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
176 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']} ]
177 outputs
= { self
.nodes
[0].getnewaddress() : Decimal(4.0) }
178 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
179 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
180 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
182 assert_raises_rpc_error(-3, "Unexpected key foo", self
.nodes
[2].fundrawtransaction
, rawtx
, {'foo':'bar'})
184 ############################################################
185 # test a fundrawtransaction with an invalid change address #
186 ############################################################
187 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
189 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']} ]
190 outputs
= { self
.nodes
[0].getnewaddress() : Decimal(4.0) }
191 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
192 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
193 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
195 assert_raises_rpc_error(-5, "changeAddress must be a valid bitcoin address", self
.nodes
[2].fundrawtransaction
, rawtx
, {'changeAddress':'foobar'})
197 ############################################################
198 # test a fundrawtransaction with a provided change address #
199 ############################################################
200 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
202 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']} ]
203 outputs
= { self
.nodes
[0].getnewaddress() : Decimal(4.0) }
204 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
205 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
206 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
208 change
= self
.nodes
[2].getnewaddress()
209 assert_raises_rpc_error(-8, "changePosition out of bounds", self
.nodes
[2].fundrawtransaction
, rawtx
, {'changeAddress':change
, 'changePosition':2})
210 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
, {'changeAddress': change
, 'changePosition': 0})
211 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
212 out
= dec_tx
['vout'][0]
213 assert_equal(change
, out
['scriptPubKey']['addresses'][0])
216 #########################################################################
217 # test a fundrawtransaction with a VIN smaller than the required amount #
218 #########################################################################
219 utx
= get_unspent(self
.nodes
[2].listunspent(), 1)
221 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']}]
222 outputs
= { self
.nodes
[0].getnewaddress() : 1.0 }
223 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
225 # 4-byte version + 1-byte vin count + 36-byte prevout then script_len
226 rawtx
= rawtx
[:82] + "0100" + rawtx
[84:]
228 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
229 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
230 assert_equal("00", dec_tx
['vin'][0]['scriptSig']['hex'])
232 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
233 fee
= rawtxfund
['fee']
234 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
237 for i
, out
in enumerate(dec_tx
['vout']):
238 totalOut
+= out
['value']
239 if out
['scriptPubKey']['addresses'][0] in outputs
:
242 assert_equal(i
, rawtxfund
['changepos'])
244 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
245 assert_equal("00", dec_tx
['vin'][0]['scriptSig']['hex'])
247 assert_equal(matchingOuts
, 1)
248 assert_equal(len(dec_tx
['vout']), 2)
251 ###########################################
252 # test a fundrawtransaction with two VINs #
253 ###########################################
254 utx
= get_unspent(self
.nodes
[2].listunspent(), 1)
255 utx2
= get_unspent(self
.nodes
[2].listunspent(), 5)
257 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']},{'txid' : utx2
['txid'], 'vout' : utx2
['vout']} ]
258 outputs
= { self
.nodes
[0].getnewaddress() : 6.0 }
259 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
260 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
261 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
263 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
264 fee
= rawtxfund
['fee']
265 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
268 for out
in dec_tx
['vout']:
269 totalOut
+= out
['value']
270 if out
['scriptPubKey']['addresses'][0] in outputs
:
273 assert_equal(matchingOuts
, 1)
274 assert_equal(len(dec_tx
['vout']), 2)
277 for vinOut
in dec_tx
['vin']:
279 if vinIn
['txid'] == vinOut
['txid']:
282 assert_equal(matchingIns
, 2) #we now must see two vins identical to vins given as params
284 #########################################################
285 # test a fundrawtransaction with two VINs and two vOUTs #
286 #########################################################
287 utx
= get_unspent(self
.nodes
[2].listunspent(), 1)
288 utx2
= get_unspent(self
.nodes
[2].listunspent(), 5)
290 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']},{'txid' : utx2
['txid'], 'vout' : utx2
['vout']} ]
291 outputs
= { self
.nodes
[0].getnewaddress() : 6.0, self
.nodes
[0].getnewaddress() : 1.0 }
292 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
293 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
294 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
296 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
297 fee
= rawtxfund
['fee']
298 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
301 for out
in dec_tx
['vout']:
302 totalOut
+= out
['value']
303 if out
['scriptPubKey']['addresses'][0] in outputs
:
306 assert_equal(matchingOuts
, 2)
307 assert_equal(len(dec_tx
['vout']), 3)
309 ##############################################
310 # test a fundrawtransaction with invalid vin #
311 ##############################################
312 inputs
= [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin!
313 outputs
= { self
.nodes
[0].getnewaddress() : 1.0}
314 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
315 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
317 assert_raises_rpc_error(-4, "Insufficient funds", self
.nodes
[2].fundrawtransaction
, rawtx
)
319 ############################################################
320 #compare fee of a standard pubkeyhash transaction
322 outputs
= {self
.nodes
[1].getnewaddress():1.1}
323 rawtx
= self
.nodes
[0].createrawtransaction(inputs
, outputs
)
324 fundedTx
= self
.nodes
[0].fundrawtransaction(rawtx
)
326 #create same transaction over sendtoaddress
327 txId
= self
.nodes
[0].sendtoaddress(self
.nodes
[1].getnewaddress(), 1.1)
328 signedFee
= self
.nodes
[0].getrawmempool(True)[txId
]['fee']
331 feeDelta
= Decimal(fundedTx
['fee']) - Decimal(signedFee
)
332 assert(feeDelta
>= 0 and feeDelta
<= feeTolerance
)
333 ############################################################
335 ############################################################
336 #compare fee of a standard pubkeyhash transaction with multiple outputs
338 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}
339 rawtx
= self
.nodes
[0].createrawtransaction(inputs
, outputs
)
340 fundedTx
= self
.nodes
[0].fundrawtransaction(rawtx
)
341 #create same transaction over sendtoaddress
342 txId
= self
.nodes
[0].sendmany("", outputs
)
343 signedFee
= self
.nodes
[0].getrawmempool(True)[txId
]['fee']
346 feeDelta
= Decimal(fundedTx
['fee']) - Decimal(signedFee
)
347 assert(feeDelta
>= 0 and feeDelta
<= feeTolerance
)
348 ############################################################
351 ############################################################
352 #compare fee of a 2of2 multisig p2sh transaction
355 addr1
= self
.nodes
[1].getnewaddress()
356 addr2
= self
.nodes
[1].getnewaddress()
358 addr1Obj
= self
.nodes
[1].validateaddress(addr1
)
359 addr2Obj
= self
.nodes
[1].validateaddress(addr2
)
361 mSigObj
= self
.nodes
[1].addmultisigaddress(2, [addr1Obj
['pubkey'], addr2Obj
['pubkey']])
364 outputs
= {mSigObj
:1.1}
365 rawtx
= self
.nodes
[0].createrawtransaction(inputs
, outputs
)
366 fundedTx
= self
.nodes
[0].fundrawtransaction(rawtx
)
368 #create same transaction over sendtoaddress
369 txId
= self
.nodes
[0].sendtoaddress(mSigObj
, 1.1)
370 signedFee
= self
.nodes
[0].getrawmempool(True)[txId
]['fee']
373 feeDelta
= Decimal(fundedTx
['fee']) - Decimal(signedFee
)
374 assert(feeDelta
>= 0 and feeDelta
<= feeTolerance
)
375 ############################################################
378 ############################################################
379 #compare fee of a standard pubkeyhash transaction
382 addr1
= self
.nodes
[1].getnewaddress()
383 addr2
= self
.nodes
[1].getnewaddress()
384 addr3
= self
.nodes
[1].getnewaddress()
385 addr4
= self
.nodes
[1].getnewaddress()
386 addr5
= self
.nodes
[1].getnewaddress()
388 addr1Obj
= self
.nodes
[1].validateaddress(addr1
)
389 addr2Obj
= self
.nodes
[1].validateaddress(addr2
)
390 addr3Obj
= self
.nodes
[1].validateaddress(addr3
)
391 addr4Obj
= self
.nodes
[1].validateaddress(addr4
)
392 addr5Obj
= self
.nodes
[1].validateaddress(addr5
)
394 mSigObj
= self
.nodes
[1].addmultisigaddress(4, [addr1Obj
['pubkey'], addr2Obj
['pubkey'], addr3Obj
['pubkey'], addr4Obj
['pubkey'], addr5Obj
['pubkey']])
397 outputs
= {mSigObj
:1.1}
398 rawtx
= self
.nodes
[0].createrawtransaction(inputs
, outputs
)
399 fundedTx
= self
.nodes
[0].fundrawtransaction(rawtx
)
401 #create same transaction over sendtoaddress
402 txId
= self
.nodes
[0].sendtoaddress(mSigObj
, 1.1)
403 signedFee
= self
.nodes
[0].getrawmempool(True)[txId
]['fee']
406 feeDelta
= Decimal(fundedTx
['fee']) - Decimal(signedFee
)
407 assert(feeDelta
>= 0 and feeDelta
<= feeTolerance
)
408 ############################################################
411 ############################################################
412 # spend a 2of2 multisig transaction over fundraw
415 addr1
= self
.nodes
[2].getnewaddress()
416 addr2
= self
.nodes
[2].getnewaddress()
418 addr1Obj
= self
.nodes
[2].validateaddress(addr1
)
419 addr2Obj
= self
.nodes
[2].validateaddress(addr2
)
421 mSigObj
= self
.nodes
[2].addmultisigaddress(2, [addr1Obj
['pubkey'], addr2Obj
['pubkey']])
424 # send 1.2 BTC to msig addr
425 txId
= self
.nodes
[0].sendtoaddress(mSigObj
, 1.2)
427 self
.nodes
[1].generate(1)
430 oldBalance
= self
.nodes
[1].getbalance()
432 outputs
= {self
.nodes
[1].getnewaddress():1.1}
433 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
434 fundedTx
= self
.nodes
[2].fundrawtransaction(rawtx
)
436 signedTx
= self
.nodes
[2].signrawtransaction(fundedTx
['hex'])
437 txId
= self
.nodes
[2].sendrawtransaction(signedTx
['hex'])
439 self
.nodes
[1].generate(1)
442 # make sure funds are received at node1
443 assert_equal(oldBalance
+Decimal('1.10000000'), self
.nodes
[1].getbalance())
445 ############################################################
448 self
.nodes
[1].node_encrypt_wallet("test")
453 # This test is not meant to test fee estimation and we'd like
454 # to be sure all txs are sent at a consistent desired feerate
455 for node
in self
.nodes
:
456 node
.settxfee(min_relay_tx_fee
)
458 connect_nodes_bi(self
.nodes
,0,1)
459 connect_nodes_bi(self
.nodes
,1,2)
460 connect_nodes_bi(self
.nodes
,0,2)
461 connect_nodes_bi(self
.nodes
,0,3)
465 self
.nodes
[1].getnewaddress()
466 self
.nodes
[1].getrawchangeaddress()
468 outputs
= {self
.nodes
[0].getnewaddress():1.1}
469 rawtx
= self
.nodes
[1].createrawtransaction(inputs
, outputs
)
470 # fund a transaction that requires a new key for the change output
471 # creating the key must be impossible because the wallet is locked
472 assert_raises_rpc_error(-4, "Keypool ran out, please call keypoolrefill first", self
.nodes
[1].fundrawtransaction
, rawtx
)
475 self
.nodes
[1].walletpassphrase("test", 100)
476 self
.nodes
[1].keypoolrefill(8) #need to refill the keypool to get an internal change address
477 self
.nodes
[1].walletlock()
479 assert_raises_rpc_error(-13, "walletpassphrase", self
.nodes
[1].sendtoaddress
, self
.nodes
[0].getnewaddress(), 1.2)
481 oldBalance
= self
.nodes
[0].getbalance()
484 outputs
= {self
.nodes
[0].getnewaddress():1.1}
485 rawtx
= self
.nodes
[1].createrawtransaction(inputs
, outputs
)
486 fundedTx
= self
.nodes
[1].fundrawtransaction(rawtx
)
488 #now we need to unlock
489 self
.nodes
[1].walletpassphrase("test", 600)
490 signedTx
= self
.nodes
[1].signrawtransaction(fundedTx
['hex'])
491 txId
= self
.nodes
[1].sendrawtransaction(signedTx
['hex'])
492 self
.nodes
[1].generate(1)
495 # make sure funds are received at node1
496 assert_equal(oldBalance
+Decimal('51.10000000'), self
.nodes
[0].getbalance())
499 ###############################################
500 # multiple (~19) inputs tx test | Compare fee #
501 ###############################################
503 #empty node1, send some small coins from node0 to node1
504 self
.nodes
[1].sendtoaddress(self
.nodes
[0].getnewaddress(), self
.nodes
[1].getbalance(), "", "", True)
506 self
.nodes
[0].generate(1)
509 for i
in range(0,20):
510 self
.nodes
[0].sendtoaddress(self
.nodes
[1].getnewaddress(), 0.01)
511 self
.nodes
[0].generate(1)
514 #fund a tx with ~20 small inputs
516 outputs
= {self
.nodes
[0].getnewaddress():0.15,self
.nodes
[0].getnewaddress():0.04}
517 rawtx
= self
.nodes
[1].createrawtransaction(inputs
, outputs
)
518 fundedTx
= self
.nodes
[1].fundrawtransaction(rawtx
)
520 #create same transaction over sendtoaddress
521 txId
= self
.nodes
[1].sendmany("", outputs
)
522 signedFee
= self
.nodes
[1].getrawmempool(True)[txId
]['fee']
525 feeDelta
= Decimal(fundedTx
['fee']) - Decimal(signedFee
)
526 assert(feeDelta
>= 0 and feeDelta
<= feeTolerance
*19) #~19 inputs
529 #############################################
530 # multiple (~19) inputs tx test | sign/send #
531 #############################################
533 #again, empty node1, send some small coins from node0 to node1
534 self
.nodes
[1].sendtoaddress(self
.nodes
[0].getnewaddress(), self
.nodes
[1].getbalance(), "", "", True)
536 self
.nodes
[0].generate(1)
539 for i
in range(0,20):
540 self
.nodes
[0].sendtoaddress(self
.nodes
[1].getnewaddress(), 0.01)
541 self
.nodes
[0].generate(1)
544 #fund a tx with ~20 small inputs
545 oldBalance
= self
.nodes
[0].getbalance()
548 outputs
= {self
.nodes
[0].getnewaddress():0.15,self
.nodes
[0].getnewaddress():0.04}
549 rawtx
= self
.nodes
[1].createrawtransaction(inputs
, outputs
)
550 fundedTx
= self
.nodes
[1].fundrawtransaction(rawtx
)
551 fundedAndSignedTx
= self
.nodes
[1].signrawtransaction(fundedTx
['hex'])
552 txId
= self
.nodes
[1].sendrawtransaction(fundedAndSignedTx
['hex'])
554 self
.nodes
[0].generate(1)
556 assert_equal(oldBalance
+Decimal('50.19000000'), self
.nodes
[0].getbalance()) #0.19+block reward
558 #####################################################
559 # test fundrawtransaction with OP_RETURN and no vin #
560 #####################################################
562 rawtx
= "0100000000010000000000000000066a047465737400000000"
563 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
565 assert_equal(len(dec_tx
['vin']), 0)
566 assert_equal(len(dec_tx
['vout']), 1)
568 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
569 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
571 assert_greater_than(len(dec_tx
['vin']), 0) # at least one vin
572 assert_equal(len(dec_tx
['vout']), 2) # one change output added
575 ##################################################
576 # test a fundrawtransaction using only watchonly #
577 ##################################################
580 outputs
= {self
.nodes
[2].getnewaddress() : watchonly_amount
/ 2}
581 rawtx
= self
.nodes
[3].createrawtransaction(inputs
, outputs
)
583 result
= self
.nodes
[3].fundrawtransaction(rawtx
, {'includeWatching': True })
584 res_dec
= self
.nodes
[0].decoderawtransaction(result
["hex"])
585 assert_equal(len(res_dec
["vin"]), 1)
586 assert_equal(res_dec
["vin"][0]["txid"], watchonly_txid
)
588 assert("fee" in result
.keys())
589 assert_greater_than(result
["changepos"], -1)
591 ###############################################################
592 # test fundrawtransaction using the entirety of watched funds #
593 ###############################################################
596 outputs
= {self
.nodes
[2].getnewaddress() : watchonly_amount
}
597 rawtx
= self
.nodes
[3].createrawtransaction(inputs
, outputs
)
599 # Backward compatibility test (2nd param is includeWatching)
600 result
= self
.nodes
[3].fundrawtransaction(rawtx
, True)
601 res_dec
= self
.nodes
[0].decoderawtransaction(result
["hex"])
602 assert_equal(len(res_dec
["vin"]), 2)
603 assert(res_dec
["vin"][0]["txid"] == watchonly_txid
or res_dec
["vin"][1]["txid"] == watchonly_txid
)
605 assert_greater_than(result
["fee"], 0)
606 assert_greater_than(result
["changepos"], -1)
607 assert_equal(result
["fee"] + res_dec
["vout"][result
["changepos"]]["value"], watchonly_amount
/ 10)
609 signedtx
= self
.nodes
[3].signrawtransaction(result
["hex"])
610 assert(not signedtx
["complete"])
611 signedtx
= self
.nodes
[0].signrawtransaction(signedtx
["hex"])
612 assert(signedtx
["complete"])
613 self
.nodes
[0].sendrawtransaction(signedtx
["hex"])
614 self
.nodes
[0].generate(1)
617 #######################
618 # Test feeRate option #
619 #######################
621 # Make sure there is exactly one input so coin selection can't skew the result
622 assert_equal(len(self
.nodes
[3].listunspent(1)), 1)
625 outputs
= {self
.nodes
[3].getnewaddress() : 1}
626 rawtx
= self
.nodes
[3].createrawtransaction(inputs
, outputs
)
627 result
= self
.nodes
[3].fundrawtransaction(rawtx
) # uses min_relay_tx_fee (set by settxfee)
628 result2
= self
.nodes
[3].fundrawtransaction(rawtx
, {"feeRate": 2*min_relay_tx_fee
})
629 result3
= self
.nodes
[3].fundrawtransaction(rawtx
, {"feeRate": 10*min_relay_tx_fee
})
630 result_fee_rate
= result
['fee'] * 1000 / count_bytes(result
['hex'])
631 assert_fee_amount(result2
['fee'], count_bytes(result2
['hex']), 2 * result_fee_rate
)
632 assert_fee_amount(result3
['fee'], count_bytes(result3
['hex']), 10 * result_fee_rate
)
634 ################################
635 # Test no address reuse occurs #
636 ################################
638 result3
= self
.nodes
[3].fundrawtransaction(rawtx
)
639 res_dec
= self
.nodes
[0].decoderawtransaction(result3
["hex"])
641 for out
in res_dec
['vout']:
642 if out
['value'] > 1.0:
643 changeaddress
+= out
['scriptPubKey']['addresses'][0]
644 assert(changeaddress
!= "")
645 nextaddr
= self
.nodes
[3].getnewaddress()
646 # Now the change address key should be removed from the keypool
647 assert(changeaddress
!= nextaddr
)
649 ######################################
650 # Test subtractFeeFromOutputs option #
651 ######################################
653 # Make sure there is exactly one input so coin selection can't skew the result
654 assert_equal(len(self
.nodes
[3].listunspent(1)), 1)
657 outputs
= {self
.nodes
[2].getnewaddress(): 1}
658 rawtx
= self
.nodes
[3].createrawtransaction(inputs
, outputs
)
660 result
= [self
.nodes
[3].fundrawtransaction(rawtx
), # uses min_relay_tx_fee (set by settxfee)
661 self
.nodes
[3].fundrawtransaction(rawtx
, {"subtractFeeFromOutputs": []}), # empty subtraction list
662 self
.nodes
[3].fundrawtransaction(rawtx
, {"subtractFeeFromOutputs": [0]}), # uses min_relay_tx_fee (set by settxfee)
663 self
.nodes
[3].fundrawtransaction(rawtx
, {"feeRate": 2*min_relay_tx_fee
}),
664 self
.nodes
[3].fundrawtransaction(rawtx
, {"feeRate": 2*min_relay_tx_fee
, "subtractFeeFromOutputs": [0]})]
666 dec_tx
= [self
.nodes
[3].decoderawtransaction(tx
['hex']) for tx
in result
]
667 output
= [d
['vout'][1 - r
['changepos']]['value'] for d
, r
in zip(dec_tx
, result
)]
668 change
= [d
['vout'][r
['changepos']]['value'] for d
, r
in zip(dec_tx
, result
)]
670 assert_equal(result
[0]['fee'], result
[1]['fee'], result
[2]['fee'])
671 assert_equal(result
[3]['fee'], result
[4]['fee'])
672 assert_equal(change
[0], change
[1])
673 assert_equal(output
[0], output
[1])
674 assert_equal(output
[0], output
[2] + result
[2]['fee'])
675 assert_equal(change
[0] + result
[0]['fee'], change
[2])
676 assert_equal(output
[3], output
[4] + result
[4]['fee'])
677 assert_equal(change
[3] + result
[3]['fee'], change
[4])
680 outputs
= {self
.nodes
[2].getnewaddress(): value
for value
in (1.0, 1.1, 1.2, 1.3)}
681 rawtx
= self
.nodes
[3].createrawtransaction(inputs
, outputs
)
683 result
= [self
.nodes
[3].fundrawtransaction(rawtx
),
684 # split the fee between outputs 0, 2, and 3, but not output 1
685 self
.nodes
[3].fundrawtransaction(rawtx
, {"subtractFeeFromOutputs": [0, 2, 3]})]
687 dec_tx
= [self
.nodes
[3].decoderawtransaction(result
[0]['hex']),
688 self
.nodes
[3].decoderawtransaction(result
[1]['hex'])]
690 # Nested list of non-change output amounts for each transaction
691 output
= [[out
['value'] for i
, out
in enumerate(d
['vout']) if i
!= r
['changepos']]
692 for d
, r
in zip(dec_tx
, result
)]
694 # List of differences in output amounts between normal and subtractFee transactions
695 share
= [o0
- o1
for o0
, o1
in zip(output
[0], output
[1])]
697 # output 1 is the same in both transactions
698 assert_equal(share
[1], 0)
700 # the other 3 outputs are smaller as a result of subtractFeeFromOutputs
701 assert_greater_than(share
[0], 0)
702 assert_greater_than(share
[2], 0)
703 assert_greater_than(share
[3], 0)
705 # outputs 2 and 3 take the same share of the fee
706 assert_equal(share
[2], share
[3])
708 # output 0 takes at least as much share of the fee, and no more than 2 satoshis more, than outputs 2 and 3
709 assert_greater_than_or_equal(share
[0], share
[2])
710 assert_greater_than_or_equal(share
[2] + Decimal(2e-8), share
[0])
712 # the fee is the same in both transactions
713 assert_equal(result
[0]['fee'], result
[1]['fee'])
715 # the total subtracted from the outputs is equal to the fee
716 assert_equal(share
[0] + share
[2] + share
[3], result
[0]['fee'])
718 if __name__
== '__main__':
719 RawTransactionsTest().main()