|
15 | 15 | class WalletGroupTest(BitcoinTestFramework):
|
16 | 16 | def set_test_params(self):
|
17 | 17 | self.setup_clean_chain = True
|
18 |
| - self.num_nodes = 3 |
19 |
| - self.extra_args = [[], [], ['-avoidpartialspends']] |
| 18 | + self.num_nodes = 4 |
| 19 | + self.extra_args = [[], [], ['-avoidpartialspends'], ["-maxapsfee=0.0001"]] |
20 | 20 | self.rpc_timeout = 480
|
21 | 21 |
|
22 | 22 | def skip_test_if_missing_module(self):
|
@@ -64,6 +64,52 @@ def run_test(self):
|
64 | 64 | assert_approx(v[0], 0.2)
|
65 | 65 | assert_approx(v[1], 1.3, 0.0001)
|
66 | 66 |
|
| 67 | + # Test 'avoid partial if warranted, even if disabled' |
| 68 | + self.sync_all() |
| 69 | + self.nodes[0].generate(1) |
| 70 | + # Nodes 1-2 now have confirmed UTXOs (letters denote destinations): |
| 71 | + # Node #1: Node #2: |
| 72 | + # - A 1.0 - D0 1.0 |
| 73 | + # - B0 1.0 - D1 0.5 |
| 74 | + # - B1 0.5 - E0 1.0 |
| 75 | + # - C0 1.0 - E1 0.5 |
| 76 | + # - C1 0.5 - F ~1.3 |
| 77 | + # - D ~0.3 |
| 78 | + assert_approx(self.nodes[1].getbalance(), 4.3, 0.0001) |
| 79 | + assert_approx(self.nodes[2].getbalance(), 4.3, 0.0001) |
| 80 | + # Sending 1.4 btc should pick one 1.0 + one more. For node #1, |
| 81 | + # this could be (A / B0 / C0) + (B1 / C1 / D). We ensure that it is |
| 82 | + # B0 + B1 or C0 + C1, because this avoids partial spends while not being |
| 83 | + # detrimental to transaction cost |
| 84 | + txid3 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.4) |
| 85 | + tx3 = self.nodes[1].getrawtransaction(txid3, True) |
| 86 | + # tx3 should have 2 inputs and 2 outputs |
| 87 | + assert_equal(2, len(tx3["vin"])) |
| 88 | + assert_equal(2, len(tx3["vout"])) |
| 89 | + # the accumulated value should be 1.5, so the outputs should be |
| 90 | + # ~0.1 and 1.4 and should come from the same destination |
| 91 | + values = [vout["value"] for vout in tx3["vout"]] |
| 92 | + values.sort() |
| 93 | + assert_approx(values[0], 0.1, 0.0001) |
| 94 | + assert_approx(values[1], 1.4) |
| 95 | + |
| 96 | + input_txids = [vin["txid"] for vin in tx3["vin"]] |
| 97 | + input_addrs = [self.nodes[1].gettransaction(txid)['details'][0]['address'] for txid in input_txids] |
| 98 | + assert_equal(input_addrs[0], input_addrs[1]) |
| 99 | + # Node 2 enforces avoidpartialspends so needs no checking here |
| 100 | + |
| 101 | + # Test wallet option maxapsfee with Node 3 |
| 102 | + addr_aps = self.nodes[3].getnewaddress() |
| 103 | + self.nodes[0].sendtoaddress(addr_aps, 1.0) |
| 104 | + self.nodes[0].sendtoaddress(addr_aps, 1.0) |
| 105 | + self.nodes[0].generate(1) |
| 106 | + txid4 = self.nodes[3].sendtoaddress(self.nodes[0].getnewaddress(), 0.1) |
| 107 | + tx4 = self.nodes[3].getrawtransaction(txid4, True) |
| 108 | + # tx4 should have 2 inputs and 2 outputs although one output would |
| 109 | + # have been enough and the transaction caused higher fees |
| 110 | + assert_equal(2, len(tx4["vin"])) |
| 111 | + assert_equal(2, len(tx4["vout"])) |
| 112 | + |
67 | 113 | # Empty out node2's wallet
|
68 | 114 | self.nodes[2].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=self.nodes[2].getbalance(), subtractfeefromamount=True)
|
69 | 115 | self.sync_all()
|
|
0 commit comments