wallet_sendall.py raw
1 #!/usr/bin/env python3
2 # Copyright (c) 2022 The Limenka 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 sendall RPC command."""
6
7 from decimal import Decimal, getcontext
8
9 from test_framework.messages import SEQUENCE_FINAL
10 from test_framework.test_framework import LimenkaTestFramework
11 from test_framework.util import (
12 assert_equal,
13 assert_greater_than,
14 assert_greater_than_or_equal,
15 assert_raises_rpc_error,
16 )
17
18 # Decorator to reset activewallet to zero utxos
19 def cleanup(func):
20 def wrapper(self):
21 try:
22 func(self)
23 finally:
24 if 0 < self.wallet.getbalances()["mine"]["trusted"]:
25 self.wallet.sendall([self.remainder_target])
26 assert_equal(0, self.wallet.getbalances()["mine"]["trusted"]) # wallet is empty
27 return wrapper
28
29 class SendallTest(LimenkaTestFramework):
30 # Setup and helpers
31 def add_options(self, parser):
32 self.add_wallet_options(parser)
33
34 def skip_test_if_missing_module(self):
35 self.skip_if_no_wallet()
36
37 def set_test_params(self):
38 getcontext().prec=10
39 self.num_nodes = 1
40 self.setup_clean_chain = True
41
42 def assert_balance_swept_completely(self, tx, balance):
43 output_sum = sum([o["value"] for o in tx["decoded"]["vout"]])
44 assert_equal(output_sum, balance + tx["fee"])
45 assert_equal(0, self.wallet.getbalances()["mine"]["trusted"]) # wallet is empty
46
47 def assert_tx_has_output(self, tx, addr, value=None):
48 for output in tx["decoded"]["vout"]:
49 if addr == output["scriptPubKey"]["address"] and value is None or value == output["value"]:
50 return
51 raise AssertionError("Output to {} not present or wrong amount".format(addr))
52
53 def assert_tx_has_outputs(self, tx, expected_outputs):
54 assert_equal(len(expected_outputs), len(tx["decoded"]["vout"]))
55 for eo in expected_outputs:
56 self.assert_tx_has_output(tx, eo["address"], eo["value"])
57
58 def add_utxos(self, amounts):
59 for a in amounts:
60 self.def_wallet.sendtoaddress(self.wallet.getnewaddress(), a)
61 self.generate(self.nodes[0], 1)
62 assert_greater_than(self.wallet.getbalances()["mine"]["trusted"], 0)
63 return self.wallet.getbalances()["mine"]["trusted"]
64
65 # Helper schema for success cases
66 def test_sendall_success(self, sendall_args, remaining_balance = 0):
67 sendall_tx_receipt = self.wallet.sendall(sendall_args)
68 self.generate(self.nodes[0], 1)
69 # wallet has remaining balance (usually empty)
70 assert_equal(remaining_balance, self.wallet.getbalances()["mine"]["trusted"])
71
72 assert_equal(sendall_tx_receipt["complete"], True)
73 return self.wallet.gettransaction(txid = sendall_tx_receipt["txid"], verbose = True)
74
75 @cleanup
76 def gen_and_clean(self):
77 self.add_utxos([15, 2, 4])
78
79 def test_cleanup(self):
80 self.log.info("Test that cleanup wrapper empties wallet")
81 self.gen_and_clean()
82 assert_equal(0, self.wallet.getbalances()["mine"]["trusted"]) # wallet is empty
83
84 # Actual tests
85 @cleanup
86 def sendall_two_utxos(self):
87 self.log.info("Testing basic sendall case without specific amounts")
88 pre_sendall_balance = self.add_utxos([10,11])
89 tx_from_wallet = self.test_sendall_success(sendall_args = [self.remainder_target])
90
91 self.assert_tx_has_outputs(tx = tx_from_wallet,
92 expected_outputs = [
93 { "address": self.remainder_target, "value": pre_sendall_balance + tx_from_wallet["fee"] } # fee is neg
94 ]
95 )
96 self.assert_balance_swept_completely(tx_from_wallet, pre_sendall_balance)
97
98 @cleanup
99 def sendall_split(self):
100 self.log.info("Testing sendall where two recipients have unspecified amount")
101 pre_sendall_balance = self.add_utxos([1, 2, 3, 15])
102 tx_from_wallet = self.test_sendall_success([self.remainder_target, self.split_target])
103
104 half = (pre_sendall_balance + tx_from_wallet["fee"]) / 2
105 self.assert_tx_has_outputs(tx_from_wallet,
106 expected_outputs = [
107 { "address": self.split_target, "value": half },
108 { "address": self.remainder_target, "value": half }
109 ]
110 )
111 self.assert_balance_swept_completely(tx_from_wallet, pre_sendall_balance)
112
113 @cleanup
114 def sendall_and_spend(self):
115 self.log.info("Testing sendall in combination with paying specified amount to recipient")
116 pre_sendall_balance = self.add_utxos([8, 13])
117 tx_from_wallet = self.test_sendall_success([{self.recipient: 5}, self.remainder_target])
118
119 self.assert_tx_has_outputs(tx_from_wallet,
120 expected_outputs = [
121 { "address": self.recipient, "value": 5 },
122 { "address": self.remainder_target, "value": pre_sendall_balance - 5 + tx_from_wallet["fee"] }
123 ]
124 )
125 self.assert_balance_swept_completely(tx_from_wallet, pre_sendall_balance)
126
127 @cleanup
128 def sendall_invalid_recipient_addresses(self):
129 self.log.info("Test having only recipient with specified amount, missing recipient with unspecified amount")
130 self.add_utxos([12, 9])
131
132 assert_raises_rpc_error(
133 -8,
134 "Must provide at least one address without a specified amount" ,
135 self.wallet.sendall,
136 [{self.recipient: 5}]
137 )
138
139 @cleanup
140 def sendall_duplicate_recipient(self):
141 self.log.info("Test duplicate destination")
142 self.add_utxos([1, 8, 3, 9])
143
144 assert_raises_rpc_error(
145 -8,
146 "Invalid parameter, duplicated address: {}".format(self.remainder_target),
147 self.wallet.sendall,
148 [self.remainder_target, self.remainder_target]
149 )
150
151 @cleanup
152 def sendall_invalid_amounts(self):
153 self.log.info("Test sending more than balance")
154 pre_sendall_balance = self.add_utxos([7, 14])
155
156 expected_tx = self.wallet.sendall(recipients=[{self.recipient: 5}, self.remainder_target], add_to_wallet=False)
157 tx = self.wallet.decoderawtransaction(expected_tx['hex'])
158 fee = 21 - sum([o["value"] for o in tx["vout"]])
159
160 assert_raises_rpc_error(-6, "Assigned more value to outputs than available funds.", self.wallet.sendall,
161 [{self.recipient: pre_sendall_balance + 1}, self.remainder_target])
162 assert_raises_rpc_error(-6, "Insufficient funds for fees after creating specified outputs.", self.wallet.sendall,
163 [{self.recipient: pre_sendall_balance}, self.remainder_target])
164 assert_raises_rpc_error(-8, "Specified output amount to {} is below dust threshold".format(self.recipient),
165 self.wallet.sendall, [{self.recipient: 0.00000001}, self.remainder_target])
166 assert_raises_rpc_error(-6, "Dynamically assigned remainder results in dust output.", self.wallet.sendall,
167 [{self.recipient: pre_sendall_balance - fee}, self.remainder_target])
168 assert_raises_rpc_error(-6, "Dynamically assigned remainder results in dust output.", self.wallet.sendall,
169 [{self.recipient: pre_sendall_balance - fee - Decimal(0.00000010)}, self.remainder_target])
170
171 # @cleanup not needed because different wallet used
172 def sendall_negative_effective_value(self):
173 self.log.info("Test that sendall fails if all UTXOs have negative effective value")
174 # Use dedicated wallet for dust amounts and unload wallet at end
175 self.nodes[0].createwallet("dustwallet")
176 dust_wallet = self.nodes[0].get_wallet_rpc("dustwallet")
177
178 self.def_wallet.sendtoaddress(dust_wallet.getnewaddress(), 0.00000400)
179 self.def_wallet.sendtoaddress(dust_wallet.getnewaddress(), 0.00000300)
180 self.generate(self.nodes[0], 1)
181 assert_greater_than(dust_wallet.getbalances()["mine"]["trusted"], 0)
182
183 assert_raises_rpc_error(-6, "Total value of UTXO pool too low to pay for transaction."
184 + " Try using lower feerate or excluding uneconomic UTXOs with 'send_max' option.",
185 dust_wallet.sendall, recipients=[self.remainder_target], fee_rate=300)
186
187 dust_wallet.unloadwallet()
188
189 @cleanup
190 def sendall_with_send_max(self):
191 self.log.info("Check that `send_max` option causes negative value UTXOs to be left behind")
192 self.add_utxos([0.00000400, 0.00000300, 1])
193
194 # sendall with send_max
195 sendall_tx_receipt = self.wallet.sendall(recipients=[self.remainder_target], fee_rate=300, send_max=True)
196 tx_from_wallet = self.wallet.gettransaction(txid = sendall_tx_receipt["txid"], verbose = True)
197
198 assert_equal(len(tx_from_wallet["decoded"]["vin"]), 1)
199 self.assert_tx_has_outputs(tx_from_wallet, [{"address": self.remainder_target, "value": 1 + tx_from_wallet["fee"]}])
200 assert_equal(self.wallet.getbalances()["mine"]["trusted"], Decimal("0.00000700"))
201
202 self.def_wallet.sendtoaddress(self.wallet.getnewaddress(), 1)
203 self.generate(self.nodes[0], 1)
204
205 @cleanup
206 def sendall_specific_inputs(self):
207 self.log.info("Test sendall with a subset of UTXO pool")
208 self.add_utxos([17, 4])
209 utxo = self.wallet.listunspent()[0]
210
211 sendall_tx_receipt = self.wallet.sendall(recipients=[self.remainder_target], inputs=[utxo])
212 tx_from_wallet = self.wallet.gettransaction(txid = sendall_tx_receipt["txid"], verbose = True)
213 assert_equal(len(tx_from_wallet["decoded"]["vin"]), 1)
214 assert_equal(len(tx_from_wallet["decoded"]["vout"]), 1)
215 assert_equal(tx_from_wallet["decoded"]["vin"][0]["txid"], utxo["txid"])
216 assert_equal(tx_from_wallet["decoded"]["vin"][0]["vout"], utxo["vout"])
217 self.assert_tx_has_output(tx_from_wallet, self.remainder_target)
218
219 self.generate(self.nodes[0], 1)
220 assert_greater_than(self.wallet.getbalances()["mine"]["trusted"], 0)
221
222 @cleanup
223 def sendall_fails_on_missing_input(self):
224 # fails because UTXO was previously spent, and wallet is empty
225 self.log.info("Test sendall fails because specified UTXO is not available")
226 self.add_utxos([16, 5])
227 spent_utxo = self.wallet.listunspent()[0]
228
229 # fails on out of bounds vout
230 assert_raises_rpc_error(-8,
231 "Input not found. UTXO ({}:{}) is not part of wallet.".format(spent_utxo["txid"], 1000),
232 self.wallet.sendall, recipients=[self.remainder_target], inputs=[{"txid": spent_utxo["txid"], "vout": 1000}])
233
234 # fails on unconfirmed spent UTXO
235 self.wallet.sendall(recipients=[self.remainder_target])
236 assert_raises_rpc_error(-8,
237 "Input not available. UTXO ({}:{}) was already spent.".format(spent_utxo["txid"], spent_utxo["vout"]),
238 self.wallet.sendall, recipients=[self.remainder_target], inputs=[spent_utxo])
239
240 # fails on specific previously spent UTXO, while other UTXOs exist
241 self.generate(self.nodes[0], 1)
242 self.add_utxos([19, 2])
243 assert_raises_rpc_error(-8,
244 "Input not available. UTXO ({}:{}) was already spent.".format(spent_utxo["txid"], spent_utxo["vout"]),
245 self.wallet.sendall, recipients=[self.remainder_target], inputs=[spent_utxo])
246
247 # fails because UTXO is unknown, while other UTXOs exist
248 foreign_utxo = self.def_wallet.listunspent()[0]
249 assert_raises_rpc_error(-8, "Input not found. UTXO ({}:{}) is not part of wallet.".format(foreign_utxo["txid"],
250 foreign_utxo["vout"]), self.wallet.sendall, recipients=[self.remainder_target],
251 inputs=[foreign_utxo])
252
253 @cleanup
254 def sendall_fails_on_no_address(self):
255 self.log.info("Test sendall fails because no address is provided")
256 self.add_utxos([19, 2])
257
258 assert_raises_rpc_error(
259 -8,
260 "Must provide at least one address without a specified amount" ,
261 self.wallet.sendall,
262 []
263 )
264
265 @cleanup
266 def sendall_fails_on_specific_inputs_with_send_max(self):
267 self.log.info("Test sendall fails because send_max is used while specific inputs are provided")
268 self.add_utxos([15, 6])
269 utxo = self.wallet.listunspent()[0]
270
271 assert_raises_rpc_error(-8,
272 "Cannot combine send_max with specific inputs.",
273 self.wallet.sendall,
274 recipients=[self.remainder_target],
275 inputs=[utxo], send_max=True)
276
277 @cleanup
278 def sendall_fails_on_high_fee(self):
279 self.log.info("Test sendall fails if the transaction fee exceeds the maxtxfee")
280 self.add_utxos([21])
281
282 assert_raises_rpc_error(
283 -4,
284 "Fee exceeds maximum configured by user",
285 self.wallet.sendall,
286 recipients=[self.remainder_target],
287 fee_rate=100000)
288
289 @cleanup
290 def sendall_fails_on_low_fee(self):
291 self.log.info("Test sendall fails if the transaction fee is lower than the minimum fee rate setting")
292 assert_raises_rpc_error(-8, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
293 self.wallet.sendall, recipients=[self.recipient], fee_rate=0.999)
294
295 @cleanup
296 def sendall_watchonly_specific_inputs(self):
297 self.log.info("Test sendall with a subset of UTXO pool in a watchonly wallet")
298 self.add_utxos([17, 4])
299 utxo = self.wallet.listunspent()[0]
300
301 self.nodes[0].createwallet(wallet_name="watching", disable_private_keys=True)
302 watchonly = self.nodes[0].get_wallet_rpc("watching")
303
304 import_req = [{
305 "desc": utxo["desc"],
306 "timestamp": 0,
307 }]
308 if self.options.descriptors:
309 watchonly.importdescriptors(import_req)
310 else:
311 watchonly.importmulti(import_req)
312
313 sendall_tx_receipt = watchonly.sendall(recipients=[self.remainder_target], inputs=[utxo])
314 psbt = sendall_tx_receipt["psbt"]
315 decoded = self.nodes[0].decodepsbt(psbt)
316 assert_equal(len(decoded["inputs"]), 1)
317 assert_equal(len(decoded["outputs"]), 1)
318 assert_equal(decoded["tx"]["vin"][0]["txid"], utxo["txid"])
319 assert_equal(decoded["tx"]["vin"][0]["vout"], utxo["vout"])
320 assert_equal(decoded["tx"]["vout"][0]["scriptPubKey"]["address"], self.remainder_target)
321
322 @cleanup
323 def sendall_with_minconf(self):
324 # utxo of 17 bicoin has 6 confirmations, utxo of 4 has 3
325 self.add_utxos([17])
326 self.generate(self.nodes[0], 2)
327 self.add_utxos([4])
328 self.generate(self.nodes[0], 2)
329
330 self.log.info("Test sendall fails because minconf is negative")
331
332 assert_raises_rpc_error(-8,
333 "Invalid minconf (minconf cannot be negative): -2",
334 self.wallet.sendall,
335 recipients=[self.remainder_target],
336 options={"minconf": -2})
337 self.log.info("Test sendall fails because minconf is used while specific inputs are provided")
338
339 utxo = self.wallet.listunspent()[0]
340 assert_raises_rpc_error(-8,
341 "Cannot combine minconf or maxconf with specific inputs.",
342 self.wallet.sendall,
343 recipients=[self.remainder_target],
344 options={"inputs": [utxo], "minconf": 2})
345
346 self.log.info("Test sendall fails because there are no utxos with enough confirmations specified by minconf")
347
348 assert_raises_rpc_error(-6,
349 "Total value of UTXO pool too low to pay for transaction. Try using lower feerate or excluding uneconomic UTXOs with 'send_max' option.",
350 self.wallet.sendall,
351 recipients=[self.remainder_target],
352 options={"minconf": 7})
353
354 self.log.info("Test sendall only spends utxos with a specified number of confirmations when minconf is used")
355 self.wallet.sendall(recipients=[self.remainder_target], fee_rate=300, options={"minconf": 6})
356
357 assert_equal(len(self.wallet.listunspent()), 1)
358 assert_equal(self.wallet.listunspent()[0]['confirmations'], 3)
359
360 # decrease minconf and show the remaining utxo is picked up
361 self.wallet.sendall(recipients=[self.remainder_target], fee_rate=300, options={"minconf": 3})
362 assert_equal(self.wallet.getbalance(), 0)
363
364 @cleanup
365 def sendall_with_maxconf(self):
366 # utxo of 17 bicoin has 6 confirmations, utxo of 4 has 3
367 self.add_utxos([17])
368 self.generate(self.nodes[0], 2)
369 self.add_utxos([4])
370 self.generate(self.nodes[0], 2)
371
372 self.log.info("Test sendall fails because there are no utxos with enough confirmations specified by maxconf")
373 assert_raises_rpc_error(-6,
374 "Total value of UTXO pool too low to pay for transaction. Try using lower feerate or excluding uneconomic UTXOs with 'send_max' option.",
375 self.wallet.sendall,
376 recipients=[self.remainder_target],
377 options={"maxconf": 1})
378
379 self.log.info("Test sendall only spends utxos with a specified number of confirmations when maxconf is used")
380 self.wallet.sendall(recipients=[self.remainder_target], fee_rate=300, options={"maxconf":4})
381 assert_equal(len(self.wallet.listunspent()), 1)
382 assert_equal(self.wallet.listunspent()[0]['confirmations'], 6)
383
384 @cleanup
385 def sendall_spends_unconfirmed_change(self):
386 self.log.info("Test that sendall spends unconfirmed change")
387 self.add_utxos([17])
388 self.wallet.sendtoaddress(self.remainder_target, 10)
389 assert_greater_than(self.wallet.getbalances()["mine"]["trusted"], 6)
390 self.test_sendall_success(sendall_args = [self.remainder_target])
391
392 assert_equal(self.wallet.getbalance(), 0)
393
394 @cleanup
395 def sendall_spends_unconfirmed_inputs_if_specified(self):
396 self.log.info("Test that sendall spends specified unconfirmed inputs")
397 self.def_wallet.sendtoaddress(self.wallet.getnewaddress(), 17)
398 self.wallet.syncwithvalidationinterfacequeue()
399 assert_equal(self.wallet.getbalances()["mine"]["untrusted_pending"], 17)
400 unspent = self.wallet.listunspent(minconf=0)[0]
401
402 self.wallet.sendall(recipients=[self.remainder_target], inputs=[unspent])
403 assert_equal(self.wallet.getbalance(), 0)
404
405 @cleanup
406 def sendall_does_ancestor_aware_funding(self):
407 self.log.info("Test that sendall does ancestor aware funding for unconfirmed inputs")
408
409 # higher parent feerate
410 self.def_wallet.sendtoaddress(address=self.wallet.getnewaddress(), amount=17, fee_rate=20)
411 self.wallet.syncwithvalidationinterfacequeue()
412
413 assert_equal(self.wallet.getbalances()["mine"]["untrusted_pending"], 17)
414 unspent = self.wallet.listunspent(minconf=0)[0]
415
416 parent_txid = unspent["txid"]
417 assert_equal(self.wallet.gettransaction(parent_txid)["confirmations"], 0)
418
419 res_1 = self.wallet.sendall(recipients=[self.def_wallet.getnewaddress()], inputs=[unspent], fee_rate=20, add_to_wallet=False, lock_unspents=True)
420 child_hex = res_1["hex"]
421
422 child_tx = self.wallet.decoderawtransaction(child_hex)
423 higher_parent_feerate_amount = child_tx["vout"][0]["value"]
424
425 # lower parent feerate
426 self.def_wallet.sendtoaddress(address=self.wallet.getnewaddress(), amount=17, fee_rate=10)
427 self.wallet.syncwithvalidationinterfacequeue()
428 assert_equal(self.wallet.getbalances()["mine"]["untrusted_pending"], 34)
429 unspent = self.wallet.listunspent(minconf=0)[0]
430
431 parent_txid = unspent["txid"]
432 assert_equal(self.wallet.gettransaction(parent_txid)["confirmations"], 0)
433
434 res_2 = self.wallet.sendall(recipients=[self.def_wallet.getnewaddress()], inputs=[unspent], fee_rate=20, add_to_wallet=False, lock_unspents=True)
435 child_hex = res_2["hex"]
436
437 child_tx = self.wallet.decoderawtransaction(child_hex)
438 lower_parent_feerate_amount = child_tx["vout"][0]["value"]
439
440 assert_greater_than(higher_parent_feerate_amount, lower_parent_feerate_amount)
441
442 @cleanup
443 def sendall_anti_fee_sniping(self):
444 self.log.info("Testing sendall does anti-fee-sniping when locktime is not specified")
445 self.add_utxos([10,11])
446 tx_from_wallet = self.test_sendall_success(sendall_args = [self.remainder_target])
447
448 # the locktime should be within 100 blocks of the
449 # block height
450 assert_greater_than_or_equal(tx_from_wallet["decoded"]["locktime"], tx_from_wallet["blockheight"] - 100)
451
452 self.log.info("Testing sendall does not do anti-fee-sniping when locktime is specified")
453 self.add_utxos([10,11])
454 txid = self.wallet.sendall(recipients=[self.remainder_target], options={"locktime":0})["txid"]
455 assert_equal(self.wallet.gettransaction(txid=txid, verbose=True)["decoded"]["locktime"], 0)
456
457 self.log.info("Testing sendall does not do anti-fee-sniping when even one of the sequences is final")
458 self.add_utxos([10, 11])
459 utxos = self.wallet.listunspent()
460 utxos[0]["sequence"] = SEQUENCE_FINAL
461 txid = self.wallet.sendall(recipients=[self.remainder_target], inputs=utxos)["txid"]
462 assert_equal(self.wallet.gettransaction(txid=txid, verbose=True)["decoded"]["locktime"], 0)
463
464 # This tests needs to be the last one otherwise @cleanup will fail with "Transaction too large" error
465 def sendall_fails_with_transaction_too_large(self):
466 self.log.info("Test that sendall fails if resulting transaction is too large")
467
468 # Force the wallet to bulk-generate the addresses we'll need
469 self.wallet.keypoolrefill(1600)
470
471 # create many inputs
472 outputs = {self.wallet.getnewaddress(): 0.000025 for _ in range(1600)}
473 self.def_wallet.sendmany(amounts=outputs)
474 self.generate(self.nodes[0], 1)
475
476 assert_raises_rpc_error(
477 -4,
478 "Transaction too large.",
479 self.wallet.sendall,
480 recipients=[self.remainder_target])
481
482 def run_test(self):
483 self.nodes[0].createwallet("activewallet")
484 self.wallet = self.nodes[0].get_wallet_rpc("activewallet")
485 self.def_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
486 self.generate(self.nodes[0], 101)
487 self.recipient = self.def_wallet.getnewaddress() # payee for a specific amount
488 self.remainder_target = self.def_wallet.getnewaddress() # address that receives everything left after payments and fees
489 self.split_target = self.def_wallet.getnewaddress() # 2nd target when splitting rest
490
491 # Test cleanup
492 self.test_cleanup()
493
494 # Basic sweep: everything to one address
495 self.sendall_two_utxos()
496
497 # Split remainder to two addresses with equal amounts
498 self.sendall_split()
499
500 # Pay recipient and sweep remainder
501 self.sendall_and_spend()
502
503 # sendall fails if no recipient has unspecified amount
504 self.sendall_invalid_recipient_addresses()
505
506 # Sendall fails if same destination is provided twice
507 self.sendall_duplicate_recipient()
508
509 # Sendall fails when trying to spend more than the balance
510 self.sendall_invalid_amounts()
511
512 # Sendall fails when wallet has no economically spendable UTXOs
513 self.sendall_negative_effective_value()
514
515 # Leave dust behind if using send_max
516 self.sendall_with_send_max()
517
518 # Sendall succeeds with specific inputs
519 self.sendall_specific_inputs()
520
521 # Fails for the right reasons on missing or previously spent UTXOs
522 self.sendall_fails_on_missing_input()
523
524 # Sendall fails when no address is provided
525 self.sendall_fails_on_no_address()
526
527 # Sendall fails when using send_max while specifying inputs
528 self.sendall_fails_on_specific_inputs_with_send_max()
529
530 # Sendall fails when providing a fee that is too high
531 self.sendall_fails_on_high_fee()
532
533 # Sendall fails when fee rate is lower than minimum
534 self.sendall_fails_on_low_fee()
535
536 # Sendall succeeds with watchonly wallets spending specific UTXOs
537 self.sendall_watchonly_specific_inputs()
538
539 # Sendall only uses outputs with at least a give number of confirmations when using minconf
540 self.sendall_with_minconf()
541
542 # Sendall only uses outputs with less than a given number of confirmation when using minconf
543 self.sendall_with_maxconf()
544
545 # Sendall discourages fee-sniping when a locktime is not specified
546 self.sendall_anti_fee_sniping()
547
548 # Sendall spends unconfirmed change
549 self.sendall_spends_unconfirmed_change()
550
551 # Sendall spends unconfirmed inputs if they are specified
552 self.sendall_spends_unconfirmed_inputs_if_specified()
553
554 # Sendall does ancestor aware funding when spending an unconfirmed UTXO
555 self.sendall_does_ancestor_aware_funding()
556
557 # Sendall fails when many inputs result to too large transaction
558 self.sendall_fails_with_transaction_too_large()
559
560 if __name__ == '__main__':
561 SendallTest(__file__).main()
562