diff options
Diffstat (limited to 'test/functional/wallet_bumpfee.py')
-rwxr-xr-x | test/functional/wallet_bumpfee.py | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py index 9a481b290b..158ef66110 100755 --- a/test/functional/wallet_bumpfee.py +++ b/test/functional/wallet_bumpfee.py @@ -53,6 +53,7 @@ class BumpFeeTest(BitcoinTestFramework): "-walletrbf={}".format(i), "-mintxfee=0.00002", "-addresstype=bech32", + "-whitelist=noban@127.0.0.1", ] for i in range(self.num_nodes)] def skip_test_if_missing_module(self): @@ -86,12 +87,13 @@ class BumpFeeTest(BitcoinTestFramework): self.test_invalid_parameters(rbf_node, peer_node, dest_address) test_segwit_bumpfee_succeeds(self, rbf_node, dest_address) test_nonrbf_bumpfee_fails(self, peer_node, dest_address) - test_notmine_bumpfee_fails(self, rbf_node, peer_node, dest_address) + test_notmine_bumpfee(self, rbf_node, peer_node, dest_address) test_bumpfee_with_descendant_fails(self, rbf_node, rbf_node_address, dest_address) test_dust_to_fee(self, rbf_node, dest_address) test_watchonly_psbt(self, peer_node, rbf_node, dest_address) test_rebumping(self, rbf_node, dest_address) test_rebumping_not_replaceable(self, rbf_node, dest_address) + test_bumpfee_already_spent(self, rbf_node, dest_address) test_unconfirmed_not_spendable(self, rbf_node, rbf_node_address) test_bumpfee_metadata(self, rbf_node, dest_address) test_locked_wallet_fails(self, rbf_node, dest_address) @@ -228,11 +230,11 @@ def test_segwit_bumpfee_succeeds(self, rbf_node, dest_address): def test_nonrbf_bumpfee_fails(self, peer_node, dest_address): self.log.info('Test that we cannot replace a non RBF transaction') not_rbfid = peer_node.sendtoaddress(dest_address, Decimal("0.00090000")) - assert_raises_rpc_error(-4, "not BIP 125 replaceable", peer_node.bumpfee, not_rbfid) + assert_raises_rpc_error(-4, "Transaction is not BIP 125 replaceable", peer_node.bumpfee, not_rbfid) self.clear_mempool() -def test_notmine_bumpfee_fails(self, rbf_node, peer_node, dest_address): +def test_notmine_bumpfee(self, rbf_node, peer_node, dest_address): self.log.info('Test that it cannot bump fee if non-owned inputs are included') # here, the rbftx has a peer_node coin and then adds a rbf_node input # Note that this test depends upon the RPC code checking input ownership prior to change outputs @@ -250,8 +252,27 @@ def test_notmine_bumpfee_fails(self, rbf_node, peer_node, dest_address): signedtx = rbf_node.signrawtransactionwithwallet(rawtx) signedtx = peer_node.signrawtransactionwithwallet(signedtx["hex"]) rbfid = rbf_node.sendrawtransaction(signedtx["hex"]) + entry = rbf_node.getmempoolentry(rbfid) + old_fee = entry["fees"]["base"] + old_feerate = int(old_fee / entry["vsize"] * Decimal(1e8)) assert_raises_rpc_error(-4, "Transaction contains inputs that don't belong to this wallet", rbf_node.bumpfee, rbfid) + + def finish_psbtbumpfee(psbt): + psbt = rbf_node.walletprocesspsbt(psbt) + psbt = peer_node.walletprocesspsbt(psbt["psbt"]) + final = rbf_node.finalizepsbt(psbt["psbt"]) + res = rbf_node.testmempoolaccept([final["hex"]]) + assert res[0]["allowed"] + assert_greater_than(res[0]["fees"]["base"], old_fee) + + self.log.info("Test that psbtbumpfee works for non-owned inputs") + psbt = rbf_node.psbtbumpfee(txid=rbfid) + finish_psbtbumpfee(psbt["psbt"]) + + psbt = rbf_node.psbtbumpfee(txid=rbfid, options={"fee_rate": old_feerate + 10}) + finish_psbtbumpfee(psbt["psbt"]) + self.clear_mempool() @@ -479,7 +500,8 @@ def test_rebumping(self, rbf_node, dest_address): self.log.info('Test that re-bumping the original tx fails, but bumping successor works') rbfid = spend_one_input(rbf_node, dest_address) bumped = rbf_node.bumpfee(rbfid, {"fee_rate": ECONOMICAL}) - assert_raises_rpc_error(-4, "already bumped", rbf_node.bumpfee, rbfid, {"fee_rate": NORMAL}) + assert_raises_rpc_error(-4, f"Cannot bump transaction {rbfid} which was already bumped by transaction {bumped['txid']}", + rbf_node.bumpfee, rbfid, {"fee_rate": NORMAL}) rbf_node.bumpfee(bumped["txid"], {"fee_rate": NORMAL}) self.clear_mempool() @@ -493,6 +515,15 @@ def test_rebumping_not_replaceable(self, rbf_node, dest_address): self.clear_mempool() +def test_bumpfee_already_spent(self, rbf_node, dest_address): + self.log.info('Test that bumping tx with already spent coin fails') + txid = spend_one_input(rbf_node, dest_address) + self.generate(rbf_node, 1) # spend coin simply by mining block with tx + spent_input = rbf_node.gettransaction(txid=txid, verbose=True)['decoded']['vin'][0] + assert_raises_rpc_error(-1, f"{spent_input['txid']}:{spent_input['vout']} is already spent", + rbf_node.bumpfee, txid, {"fee_rate": NORMAL}) + + def test_unconfirmed_not_spendable(self, rbf_node, rbf_node_address): self.log.info('Test that unconfirmed outputs from bumped txns are not spendable') rbfid = spend_one_input(rbf_node, rbf_node_address) @@ -604,7 +635,7 @@ def test_no_more_inputs_fails(self, rbf_node, dest_address): # feerate rbf requires confirmed outputs when change output doesn't exist or is insufficient self.generatetoaddress(rbf_node, 1, dest_address) # spend all funds, no change output - rbfid = rbf_node.sendtoaddress(rbf_node.getnewaddress(), rbf_node.getbalance(), "", "", True) + rbfid = rbf_node.sendall(recipients=[rbf_node.getnewaddress()])['txid'] assert_raises_rpc_error(-4, "Unable to create transaction. Insufficient funds", rbf_node.bumpfee, rbfid) self.clear_mempool() |