Skip to content

Commit 30568d3

Browse files
author
MarcoFalke
committed
Merge #19778: test: Fix intermittent issue in wallet_bumpfee
fafc9d5 test: Fix intermittent issue in wallet_bumpfee (MarcoFalke) fa347b2 test: Select at least the fee in wallet_bumpfee to avoid negative amounts (MarcoFalke) Pull request description: With a "dirty" mempool a transaction might fail to be accepted intermittently. For example, * https://travis-ci.org/github/bitcoin-core/gui/jobs/719916499#L6773 Fails acceptance * https://travis-ci.org/github/bitcoin-core/gui/jobs/719916499#L6954 Test fails Fix the issue by clearing the mempool between subtests ACKs for top commit: promag: Code review ACK fafc9d5. Tree-SHA512: 23fb6decb6343d19eafddcbdb7da0551f6be11325d1c97c30e563944000aeb02bcc4b24904d204b132c093dc1acf28445fa1fd08bfe8d8b52ddd1de51c33eeb6
2 parents 93ab136 + fafc9d5 commit 30568d3

File tree

1 file changed

+53
-25
lines changed

1 file changed

+53
-25
lines changed

test/functional/wallet_bumpfee.py

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ def set_test_params(self):
5050
def skip_test_if_missing_module(self):
5151
self.skip_if_no_wallet()
5252

53+
def clear_mempool(self):
54+
# Clear mempool between subtests. The subtests may only depend on chainstate (utxos)
55+
self.nodes[1].generate(1)
56+
self.sync_all()
57+
5358
def run_test(self):
5459
# Encrypt wallet for test_locked_wallet_fails test
5560
self.nodes[1].encryptwallet(WALLET_PASSPHRASE)
@@ -71,7 +76,7 @@ def run_test(self):
7176

7277
self.log.info("Running tests")
7378
dest_address = peer_node.getnewaddress()
74-
test_invalid_parameters(rbf_node, dest_address)
79+
self.test_invalid_parameters(rbf_node, dest_address)
7580
test_simple_bumpfee_succeeds(self, "default", rbf_node, peer_node, dest_address)
7681
test_simple_bumpfee_succeeds(self, "fee_rate", rbf_node, peer_node, dest_address)
7782
test_feerate_args(self, rbf_node, peer_node, dest_address)
@@ -93,28 +98,30 @@ def run_test(self):
9398
test_small_output_with_feerate_succeeds(self, rbf_node, dest_address)
9499
test_no_more_inputs_fails(self, rbf_node, dest_address)
95100

96-
def test_invalid_parameters(node, dest_address):
97-
txid = spend_one_input(node, dest_address)
98-
# invalid estimate mode
99-
assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", node.bumpfee, txid, {
100-
"estimate_mode": "moo",
101-
})
102-
assert_raises_rpc_error(-3, "Expected type string", node.bumpfee, txid, {
103-
"estimate_mode": 38,
104-
})
105-
assert_raises_rpc_error(-3, "Expected type string", node.bumpfee, txid, {
106-
"estimate_mode": {
107-
"foo": "bar",
108-
},
109-
})
110-
assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", node.bumpfee, txid, {
111-
"estimate_mode": Decimal("3.141592"),
112-
})
113-
# confTarget and conf_target
114-
assert_raises_rpc_error(-8, "confTarget and conf_target options should not both be set", node.bumpfee, txid, {
115-
"confTarget": 123,
116-
"conf_target": 456,
117-
})
101+
def test_invalid_parameters(self, node, dest_address):
102+
txid = spend_one_input(node, dest_address)
103+
# invalid estimate mode
104+
assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", node.bumpfee, txid, {
105+
"estimate_mode": "moo",
106+
})
107+
assert_raises_rpc_error(-3, "Expected type string", node.bumpfee, txid, {
108+
"estimate_mode": 38,
109+
})
110+
assert_raises_rpc_error(-3, "Expected type string", node.bumpfee, txid, {
111+
"estimate_mode": {
112+
"foo": "bar",
113+
},
114+
})
115+
assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", node.bumpfee, txid, {
116+
"estimate_mode": Decimal("3.141592"),
117+
})
118+
# confTarget and conf_target
119+
assert_raises_rpc_error(-8, "confTarget and conf_target options should not both be set", node.bumpfee, txid, {
120+
"confTarget": 123,
121+
"conf_target": 456,
122+
})
123+
self.clear_mempool()
124+
118125

119126
def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address):
120127
self.log.info('Test simple bumpfee: {}'.format(mode))
@@ -148,6 +155,7 @@ def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address):
148155
bumpedwtx = rbf_node.gettransaction(bumped_tx["txid"])
149156
assert_equal(oldwtx["replaced_by_txid"], bumped_tx["txid"])
150157
assert_equal(bumpedwtx["replaces_txid"], rbfid)
158+
self.clear_mempool()
151159

152160

153161
def test_feerate_args(self, rbf_node, peer_node, dest_address):
@@ -167,6 +175,7 @@ def test_feerate_args(self, rbf_node, peer_node, dest_address):
167175
assert_raises_rpc_error(-3, "Amount out of range", rbf_node.bumpfee, rbfid, {"fee_rate": -1})
168176

169177
assert_raises_rpc_error(-4, "is too high (cannot be higher than", rbf_node.bumpfee, rbfid, {"fee_rate": TOO_HIGH})
178+
self.clear_mempool()
170179

171180

172181
def test_segwit_bumpfee_succeeds(self, rbf_node, dest_address):
@@ -198,33 +207,37 @@ def test_segwit_bumpfee_succeeds(self, rbf_node, dest_address):
198207
bumped_tx = rbf_node.bumpfee(rbfid)
199208
assert bumped_tx["txid"] in rbf_node.getrawmempool()
200209
assert rbfid not in rbf_node.getrawmempool()
210+
self.clear_mempool()
201211

202212

203213
def test_nonrbf_bumpfee_fails(self, peer_node, dest_address):
204214
self.log.info('Test that we cannot replace a non RBF transaction')
205215
not_rbfid = peer_node.sendtoaddress(dest_address, Decimal("0.00090000"))
206216
assert_raises_rpc_error(-4, "not BIP 125 replaceable", peer_node.bumpfee, not_rbfid)
217+
self.clear_mempool()
207218

208219

209220
def test_notmine_bumpfee_fails(self, rbf_node, peer_node, dest_address):
210221
self.log.info('Test that it cannot bump fee if non-owned inputs are included')
211222
# here, the rbftx has a peer_node coin and then adds a rbf_node input
212223
# Note that this test depends upon the RPC code checking input ownership prior to change outputs
213224
# (since it can't use fundrawtransaction, it lacks a proper change output)
214-
utxos = [node.listunspent()[-1] for node in (rbf_node, peer_node)]
225+
fee = Decimal("0.001")
226+
utxos = [node.listunspent(query_options={'minimumAmount': fee})[-1] for node in (rbf_node, peer_node)]
215227
inputs = [{
216228
"txid": utxo["txid"],
217229
"vout": utxo["vout"],
218230
"address": utxo["address"],
219231
"sequence": BIP125_SEQUENCE_NUMBER
220232
} for utxo in utxos]
221-
output_val = sum(utxo["amount"] for utxo in utxos) - Decimal("0.001")
233+
output_val = sum(utxo["amount"] for utxo in utxos) - fee
222234
rawtx = rbf_node.createrawtransaction(inputs, {dest_address: output_val})
223235
signedtx = rbf_node.signrawtransactionwithwallet(rawtx)
224236
signedtx = peer_node.signrawtransactionwithwallet(signedtx["hex"])
225237
rbfid = rbf_node.sendrawtransaction(signedtx["hex"])
226238
assert_raises_rpc_error(-4, "Transaction contains inputs that don't belong to this wallet",
227239
rbf_node.bumpfee, rbfid)
240+
self.clear_mempool()
228241

229242

230243
def test_bumpfee_with_descendant_fails(self, rbf_node, rbf_node_address, dest_address):
@@ -235,6 +248,7 @@ def test_bumpfee_with_descendant_fails(self, rbf_node, rbf_node_address, dest_ad
235248
tx = rbf_node.signrawtransactionwithwallet(tx)
236249
rbf_node.sendrawtransaction(tx["hex"])
237250
assert_raises_rpc_error(-8, "Transaction has descendants in the wallet", rbf_node.bumpfee, parent_id)
251+
self.clear_mempool()
238252

239253

240254
def test_small_output_with_feerate_succeeds(self, rbf_node, dest_address):
@@ -276,6 +290,7 @@ def test_small_output_with_feerate_succeeds(self, rbf_node, dest_address):
276290

277291
rbf_node.generatetoaddress(1, rbf_node.getnewaddress())
278292
assert_equal(rbf_node.gettransaction(rbfid)["confirmations"], 1)
293+
self.clear_mempool()
279294

280295

281296
def test_dust_to_fee(self, rbf_node, dest_address):
@@ -298,6 +313,7 @@ def test_dust_to_fee(self, rbf_node, dest_address):
298313
assert_equal(len(fulltx["vout"]), 2)
299314
assert_equal(len(full_bumped_tx["vout"]), 1) # change output is eliminated
300315
assert_equal(full_bumped_tx["vout"][0]['value'], Decimal("0.00050000"))
316+
self.clear_mempool()
301317

302318

303319
def test_settxfee(self, rbf_node, dest_address):
@@ -320,6 +336,8 @@ def test_settxfee(self, rbf_node, dest_address):
320336
assert_raises_rpc_error(-8, "txfee cannot be more than wallet max tx fee", rbf_node.settxfee, Decimal('0.00003'))
321337
self.restart_node(1, self.extra_args[1])
322338
rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
339+
self.connect_nodes(1, 0)
340+
self.clear_mempool()
323341

324342

325343
def test_maxtxfee_fails(self, rbf_node, dest_address):
@@ -333,6 +351,8 @@ def test_maxtxfee_fails(self, rbf_node, dest_address):
333351
assert_raises_rpc_error(-4, "Unable to create transaction. Fee exceeds maximum configured by -maxtxfee", rbf_node.bumpfee, rbfid)
334352
self.restart_node(1, self.extra_args[1])
335353
rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
354+
self.connect_nodes(1, 0)
355+
self.clear_mempool()
336356

337357

338358
def test_watchonly_psbt(self, peer_node, rbf_node, dest_address):
@@ -415,6 +435,7 @@ def test_watchonly_psbt(self, peer_node, rbf_node, dest_address):
415435

416436
rbf_node.unloadwallet("watcher")
417437
rbf_node.unloadwallet("signer")
438+
self.clear_mempool()
418439

419440

420441
def test_rebumping(self, rbf_node, dest_address):
@@ -423,6 +444,7 @@ def test_rebumping(self, rbf_node, dest_address):
423444
bumped = rbf_node.bumpfee(rbfid, {"fee_rate": ECONOMICAL})
424445
assert_raises_rpc_error(-4, "already bumped", rbf_node.bumpfee, rbfid, {"fee_rate": NORMAL})
425446
rbf_node.bumpfee(bumped["txid"], {"fee_rate": NORMAL})
447+
self.clear_mempool()
426448

427449

428450
def test_rebumping_not_replaceable(self, rbf_node, dest_address):
@@ -431,6 +453,7 @@ def test_rebumping_not_replaceable(self, rbf_node, dest_address):
431453
bumped = rbf_node.bumpfee(rbfid, {"fee_rate": ECONOMICAL, "replaceable": False})
432454
assert_raises_rpc_error(-4, "Transaction is not BIP 125 replaceable", rbf_node.bumpfee, bumped["txid"],
433455
{"fee_rate": NORMAL})
456+
self.clear_mempool()
434457

435458

436459
def test_unconfirmed_not_spendable(self, rbf_node, rbf_node_address):
@@ -470,6 +493,7 @@ def test_unconfirmed_not_spendable(self, rbf_node, rbf_node_address):
470493
assert_equal(
471494
sum(1 for t in rbf_node.listunspent(minconf=0, include_unsafe=False)
472495
if t["txid"] == rbfid and t["address"] == rbf_node_address and t["spendable"]), 1)
496+
self.clear_mempool()
473497

474498

475499
def test_bumpfee_metadata(self, rbf_node, dest_address):
@@ -481,6 +505,7 @@ def test_bumpfee_metadata(self, rbf_node, dest_address):
481505
bumped_wtx = rbf_node.gettransaction(bumped_tx["txid"])
482506
assert_equal(bumped_wtx["comment"], "comment value")
483507
assert_equal(bumped_wtx["to"], "to value")
508+
self.clear_mempool()
484509

485510

486511
def test_locked_wallet_fails(self, rbf_node, dest_address):
@@ -490,6 +515,7 @@ def test_locked_wallet_fails(self, rbf_node, dest_address):
490515
assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first.",
491516
rbf_node.bumpfee, rbfid)
492517
rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
518+
self.clear_mempool()
493519

494520

495521
def test_change_script_match(self, rbf_node, dest_address):
@@ -510,6 +536,7 @@ def get_change_address(tx):
510536
assert_equal(change_addresses, get_change_address(bumped_total_tx['txid']))
511537
bumped_rate_tx = rbf_node.bumpfee(bumped_total_tx["txid"])
512538
assert_equal(change_addresses, get_change_address(bumped_rate_tx['txid']))
539+
self.clear_mempool()
513540

514541

515542
def spend_one_input(node, dest_address, change_size=Decimal("0.00049000")):
@@ -548,6 +575,7 @@ def test_no_more_inputs_fails(self, rbf_node, dest_address):
548575
# spend all funds, no change output
549576
rbfid = rbf_node.sendtoaddress(rbf_node.getnewaddress(), rbf_node.getbalance(), "", "", True)
550577
assert_raises_rpc_error(-4, "Unable to create transaction. Insufficient funds", rbf_node.bumpfee, rbfid)
578+
self.clear_mempool()
551579

552580

553581
if __name__ == "__main__":

0 commit comments

Comments
 (0)