|
27 | 27 | assert_greater_than,
|
28 | 28 | assert_raises_rpc_error,
|
29 | 29 | get_fee,
|
| 30 | + find_vout_for_address, |
30 | 31 | )
|
31 | 32 | from test_framework.wallet import MiniWallet
|
32 | 33 |
|
@@ -109,6 +110,7 @@ def run_test(self):
|
109 | 110 | test_small_output_with_feerate_succeeds(self, rbf_node, dest_address)
|
110 | 111 | test_no_more_inputs_fails(self, rbf_node, dest_address)
|
111 | 112 | self.test_bump_back_to_yourself()
|
| 113 | + self.test_provided_change_pos(rbf_node) |
112 | 114 |
|
113 | 115 | # Context independent tests
|
114 | 116 | test_feerate_checks_replaced_outputs(self, rbf_node, peer_node)
|
@@ -174,6 +176,13 @@ def test_invalid_parameters(self, rbf_node, peer_node, dest_address):
|
174 | 176 | assert_raises_rpc_error(-8, "Invalid parameter, duplicate key: data",
|
175 | 177 | rbf_node.bumpfee, rbfid, {"outputs": [{"data": "deadbeef"}, {"data": "deadbeef"}]})
|
176 | 178 |
|
| 179 | + self.log.info("Test reduce_output option") |
| 180 | + assert_raises_rpc_error(-1, "JSON integer out of range", rbf_node.bumpfee, rbfid, {"reduce_output": -1}) |
| 181 | + assert_raises_rpc_error(-8, "Change position is out of range", rbf_node.bumpfee, rbfid, {"reduce_output": 2}) |
| 182 | + |
| 183 | + self.log.info("Test outputs and reduce_output cannot both be provided") |
| 184 | + assert_raises_rpc_error(-8, "outputs and reduce_output cannot both be specified simultaneously", rbf_node.bumpfee, rbfid, {"reduce_output": 2, "outputs": [{dest_address: 0.1}]}) |
| 185 | + |
177 | 186 | self.clear_mempool()
|
178 | 187 |
|
179 | 188 | def test_bump_back_to_yourself(self):
|
@@ -225,6 +234,35 @@ def test_bump_back_to_yourself(self):
|
225 | 234 |
|
226 | 235 | node.unloadwallet("back_to_yourself")
|
227 | 236 |
|
| 237 | + def test_provided_change_pos(self, rbf_node): |
| 238 | + self.log.info("Test the reduce_output option") |
| 239 | + |
| 240 | + change_addr = rbf_node.getnewaddress() |
| 241 | + dest_addr = rbf_node.getnewaddress() |
| 242 | + assert_equal(rbf_node.getaddressinfo(change_addr)["ischange"], False) |
| 243 | + assert_equal(rbf_node.getaddressinfo(dest_addr)["ischange"], False) |
| 244 | + |
| 245 | + send_res = rbf_node.send(outputs=[{dest_addr: 1}], options={"change_address": change_addr}) |
| 246 | + assert send_res["complete"] |
| 247 | + txid = send_res["txid"] |
| 248 | + |
| 249 | + tx = rbf_node.gettransaction(txid=txid, verbose=True) |
| 250 | + assert_equal(len(tx["decoded"]["vout"]), 2) |
| 251 | + |
| 252 | + change_pos = find_vout_for_address(rbf_node, txid, change_addr) |
| 253 | + change_value = tx["decoded"]["vout"][change_pos]["value"] |
| 254 | + |
| 255 | + bumped = rbf_node.bumpfee(txid, {"reduce_output": change_pos}) |
| 256 | + new_txid = bumped["txid"] |
| 257 | + |
| 258 | + new_tx = rbf_node.gettransaction(txid=new_txid, verbose=True) |
| 259 | + assert_equal(len(new_tx["decoded"]["vout"]), 2) |
| 260 | + new_change_pos = find_vout_for_address(rbf_node, new_txid, change_addr) |
| 261 | + new_change_value = new_tx["decoded"]["vout"][new_change_pos]["value"] |
| 262 | + |
| 263 | + assert_greater_than(change_value, new_change_value) |
| 264 | + |
| 265 | + |
228 | 266 | def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address):
|
229 | 267 | self.log.info('Test simple bumpfee: {}'.format(mode))
|
230 | 268 | rbfid = spend_one_input(rbf_node, dest_address)
|
|
0 commit comments