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
, BITCOIND_PROC_WAIT_TIMEOUT
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
):
19 self
.setup_clean_chain
= True
21 def setup_network(self
, split
=False):
24 connect_nodes_bi(self
.nodes
, 0, 1)
25 connect_nodes_bi(self
.nodes
, 1, 2)
26 connect_nodes_bi(self
.nodes
, 0, 2)
27 connect_nodes_bi(self
.nodes
, 0, 3)
30 min_relay_tx_fee
= self
.nodes
[0].getnetworkinfo()['relayfee']
31 # This test is not meant to test fee estimation and we'd like
32 # to be sure all txs are sent at a consistent desired feerate
33 for node
in self
.nodes
:
34 node
.settxfee(min_relay_tx_fee
)
36 # if the fee's positive delta is higher than this value tests will fail,
37 # neg. delta always fail the tests.
38 # The size of the signature of every input may be at most 2 bytes larger
39 # than a minimum sized signature.
41 # = 2 bytes * minRelayTxFeePerByte
42 feeTolerance
= 2 * min_relay_tx_fee
/1000
44 self
.nodes
[2].generate(1)
46 self
.nodes
[0].generate(121)
49 # ensure that setting changePosition in fundraw with an exact match is handled properly
50 rawmatch
= self
.nodes
[2].createrawtransaction([], {self
.nodes
[2].getnewaddress():50})
51 rawmatch
= self
.nodes
[2].fundrawtransaction(rawmatch
, {"changePosition":1, "subtractFeeFromOutputs":[0]})
52 assert_equal(rawmatch
["changepos"], -1)
54 watchonly_address
= self
.nodes
[0].getnewaddress()
55 watchonly_pubkey
= self
.nodes
[0].validateaddress(watchonly_address
)["pubkey"]
56 watchonly_amount
= Decimal(200)
57 self
.nodes
[3].importpubkey(watchonly_pubkey
, "", True)
58 watchonly_txid
= self
.nodes
[0].sendtoaddress(watchonly_address
, watchonly_amount
)
59 self
.nodes
[0].sendtoaddress(self
.nodes
[3].getnewaddress(), watchonly_amount
/ 10)
61 self
.nodes
[0].sendtoaddress(self
.nodes
[2].getnewaddress(), 1.5)
62 self
.nodes
[0].sendtoaddress(self
.nodes
[2].getnewaddress(), 1.0)
63 self
.nodes
[0].sendtoaddress(self
.nodes
[2].getnewaddress(), 5.0)
65 self
.nodes
[0].generate(1)
72 outputs
= { self
.nodes
[0].getnewaddress() : 1.0 }
73 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
74 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
75 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
76 fee
= rawtxfund
['fee']
77 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
78 assert(len(dec_tx
['vin']) > 0) #test that we have enough inputs
80 ##############################
81 # simple test with two coins #
82 ##############################
84 outputs
= { self
.nodes
[0].getnewaddress() : 2.2 }
85 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
86 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
88 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
89 fee
= rawtxfund
['fee']
90 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
91 assert(len(dec_tx
['vin']) > 0) #test if we have enough inputs
93 ##############################
94 # simple test with two coins #
95 ##############################
97 outputs
= { self
.nodes
[0].getnewaddress() : 2.6 }
98 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
99 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
101 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
102 fee
= rawtxfund
['fee']
103 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
104 assert(len(dec_tx
['vin']) > 0)
105 assert_equal(dec_tx
['vin'][0]['scriptSig']['hex'], '')
108 ################################
109 # simple test with two outputs #
110 ################################
112 outputs
= { self
.nodes
[0].getnewaddress() : 2.6, self
.nodes
[1].getnewaddress() : 2.5 }
113 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
114 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
116 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
117 fee
= rawtxfund
['fee']
118 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
120 for out
in dec_tx
['vout']:
121 totalOut
+= out
['value']
123 assert(len(dec_tx
['vin']) > 0)
124 assert_equal(dec_tx
['vin'][0]['scriptSig']['hex'], '')
127 #########################################################################
128 # test a fundrawtransaction with a VIN greater than the required amount #
129 #########################################################################
130 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
132 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']}]
133 outputs
= { self
.nodes
[0].getnewaddress() : 1.0 }
134 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
135 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
136 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
138 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
139 fee
= rawtxfund
['fee']
140 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
142 for out
in dec_tx
['vout']:
143 totalOut
+= out
['value']
145 assert_equal(fee
+ totalOut
, utx
['amount']) #compare vin total and totalout+fee
148 #####################################################################
149 # test a fundrawtransaction with which will not get a change output #
150 #####################################################################
151 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
153 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']}]
154 outputs
= { self
.nodes
[0].getnewaddress() : Decimal(5.0) - fee
- feeTolerance
}
155 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
156 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
157 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
159 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
160 fee
= rawtxfund
['fee']
161 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
163 for out
in dec_tx
['vout']:
164 totalOut
+= out
['value']
166 assert_equal(rawtxfund
['changepos'], -1)
167 assert_equal(fee
+ totalOut
, utx
['amount']) #compare vin total and totalout+fee
170 ####################################################
171 # test a fundrawtransaction with an invalid option #
172 ####################################################
173 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
175 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']} ]
176 outputs
= { self
.nodes
[0].getnewaddress() : Decimal(4.0) }
177 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
178 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
179 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
181 assert_raises_jsonrpc(-3, "Unexpected key foo", self
.nodes
[2].fundrawtransaction
, rawtx
, {'foo':'bar'})
183 ############################################################
184 # test a fundrawtransaction with an invalid change address #
185 ############################################################
186 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
188 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']} ]
189 outputs
= { self
.nodes
[0].getnewaddress() : Decimal(4.0) }
190 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
191 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
192 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
194 assert_raises_jsonrpc(-5, "changeAddress must be a valid bitcoin address", self
.nodes
[2].fundrawtransaction
, rawtx
, {'changeAddress':'foobar'})
196 ############################################################
197 # test a fundrawtransaction with a provided change address #
198 ############################################################
199 utx
= get_unspent(self
.nodes
[2].listunspent(), 5)
201 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']} ]
202 outputs
= { self
.nodes
[0].getnewaddress() : Decimal(4.0) }
203 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
204 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
205 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
207 change
= self
.nodes
[2].getnewaddress()
208 assert_raises_jsonrpc(-8, "changePosition out of bounds", self
.nodes
[2].fundrawtransaction
, rawtx
, {'changeAddress':change
, 'changePosition':2})
209 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
, {'changeAddress': change
, 'changePosition': 0})
210 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
211 out
= dec_tx
['vout'][0]
212 assert_equal(change
, out
['scriptPubKey']['addresses'][0])
215 #########################################################################
216 # test a fundrawtransaction with a VIN smaller than the required amount #
217 #########################################################################
218 utx
= get_unspent(self
.nodes
[2].listunspent(), 1)
220 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']}]
221 outputs
= { self
.nodes
[0].getnewaddress() : 1.0 }
222 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
224 # 4-byte version + 1-byte vin count + 36-byte prevout then script_len
225 rawtx
= rawtx
[:82] + "0100" + rawtx
[84:]
227 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
228 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
229 assert_equal("00", dec_tx
['vin'][0]['scriptSig']['hex'])
231 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
232 fee
= rawtxfund
['fee']
233 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
236 for i
, out
in enumerate(dec_tx
['vout']):
237 totalOut
+= out
['value']
238 if out
['scriptPubKey']['addresses'][0] in outputs
:
241 assert_equal(i
, rawtxfund
['changepos'])
243 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
244 assert_equal("00", dec_tx
['vin'][0]['scriptSig']['hex'])
246 assert_equal(matchingOuts
, 1)
247 assert_equal(len(dec_tx
['vout']), 2)
250 ###########################################
251 # test a fundrawtransaction with two VINs #
252 ###########################################
253 utx
= get_unspent(self
.nodes
[2].listunspent(), 1)
254 utx2
= get_unspent(self
.nodes
[2].listunspent(), 5)
256 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']},{'txid' : utx2
['txid'], 'vout' : utx2
['vout']} ]
257 outputs
= { self
.nodes
[0].getnewaddress() : 6.0 }
258 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
259 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
260 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
262 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
263 fee
= rawtxfund
['fee']
264 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
267 for out
in dec_tx
['vout']:
268 totalOut
+= out
['value']
269 if out
['scriptPubKey']['addresses'][0] in outputs
:
272 assert_equal(matchingOuts
, 1)
273 assert_equal(len(dec_tx
['vout']), 2)
276 for vinOut
in dec_tx
['vin']:
278 if vinIn
['txid'] == vinOut
['txid']:
281 assert_equal(matchingIns
, 2) #we now must see two vins identical to vins given as params
283 #########################################################
284 # test a fundrawtransaction with two VINs and two vOUTs #
285 #########################################################
286 utx
= get_unspent(self
.nodes
[2].listunspent(), 1)
287 utx2
= get_unspent(self
.nodes
[2].listunspent(), 5)
289 inputs
= [ {'txid' : utx
['txid'], 'vout' : utx
['vout']},{'txid' : utx2
['txid'], 'vout' : utx2
['vout']} ]
290 outputs
= { self
.nodes
[0].getnewaddress() : 6.0, self
.nodes
[0].getnewaddress() : 1.0 }
291 rawtx
= self
.nodes
[2].createrawtransaction(inputs
, outputs
)
292 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtx
)
293 assert_equal(utx
['txid'], dec_tx
['vin'][0]['txid'])
295 rawtxfund
= self
.nodes
[2].fundrawtransaction(rawtx
)
296 fee
= rawtxfund
['fee']
297 dec_tx
= self
.nodes
[2].decoderawtransaction(rawtxfund
['hex'])
300 for out
in dec_tx
['vout']:
301 totalOut
+= out
['value']
302 if out
['scriptPubKey']['addresses'][0] in outputs
:
305 assert_equal(matchingOuts
, 2)
306 assert_equal(len(dec_tx
['vout']), 3)
308 ##############################################
309 # test a fundrawtransaction with invalid vin #
310 ##############################################
311 listunspent
= self
.nodes
[2].listunspent()
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_jsonrpc(-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_jsonrpc(-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_jsonrpc(-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()