mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-22 23:07:59 +01:00
For feebump, ignore abandoned descendant spends
To be eligible for fee-bumping, a transaction must not have any of its outputs (eg - change) spent in other unconfirmed transactions in the wallet. However, this check should not apply to abandoned transactions. A new test case is added to cover this case.
This commit is contained in:
parent
9e229a542f
commit
f9ce0eadf4
2 changed files with 31 additions and 2 deletions
|
@ -648,8 +648,7 @@ bool CWallet::HasWalletSpend(const CTransactionRef& tx) const
|
||||||
AssertLockHeld(cs_wallet);
|
AssertLockHeld(cs_wallet);
|
||||||
const uint256& txid = tx->GetHash();
|
const uint256& txid = tx->GetHash();
|
||||||
for (unsigned int i = 0; i < tx->vout.size(); ++i) {
|
for (unsigned int i = 0; i < tx->vout.size(); ++i) {
|
||||||
auto iter = mapTxSpends.find(COutPoint(txid, i));
|
if (IsSpent(COutPoint(txid, i))) {
|
||||||
if (iter != mapTxSpends.end()) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,7 @@ class BumpFeeTest(BitcoinTestFramework):
|
||||||
test_nonrbf_bumpfee_fails(self, peer_node, dest_address)
|
test_nonrbf_bumpfee_fails(self, peer_node, dest_address)
|
||||||
test_notmine_bumpfee(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_bumpfee_with_descendant_fails(self, rbf_node, rbf_node_address, dest_address)
|
||||||
|
test_bumpfee_with_abandoned_descendant_succeeds(self, rbf_node, rbf_node_address, dest_address)
|
||||||
test_dust_to_fee(self, rbf_node, dest_address)
|
test_dust_to_fee(self, rbf_node, dest_address)
|
||||||
test_watchonly_psbt(self, peer_node, rbf_node, dest_address)
|
test_watchonly_psbt(self, peer_node, rbf_node, dest_address)
|
||||||
test_rebumping(self, rbf_node, dest_address)
|
test_rebumping(self, rbf_node, dest_address)
|
||||||
|
@ -286,6 +287,35 @@ def test_bumpfee_with_descendant_fails(self, rbf_node, rbf_node_address, dest_ad
|
||||||
self.clear_mempool()
|
self.clear_mempool()
|
||||||
|
|
||||||
|
|
||||||
|
def test_bumpfee_with_abandoned_descendant_succeeds(self, rbf_node, rbf_node_address, dest_address):
|
||||||
|
self.log.info('Test that fee can be bumped when it has abandoned descendant')
|
||||||
|
# parent is send-to-self, so we don't have to check which output is change when creating the child tx
|
||||||
|
parent_id = spend_one_input(rbf_node, rbf_node_address)
|
||||||
|
# Submit child transaction with low fee
|
||||||
|
child_id = rbf_node.send(outputs={dest_address: 0.00020000},
|
||||||
|
options={"inputs": [{"txid": parent_id, "vout": 0}], "fee_rate": 2})["txid"]
|
||||||
|
assert child_id in rbf_node.getrawmempool()
|
||||||
|
|
||||||
|
# Restart the node with higher min relay fee so the descendant tx is no longer in mempool so that we can abandon it
|
||||||
|
self.restart_node(1, ['-minrelaytxfee=0.00005'] + self.extra_args[1])
|
||||||
|
rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
|
||||||
|
self.connect_nodes(1, 0)
|
||||||
|
assert parent_id in rbf_node.getrawmempool()
|
||||||
|
assert child_id not in rbf_node.getrawmempool()
|
||||||
|
# Should still raise an error even if not in mempool
|
||||||
|
assert_raises_rpc_error(-8, "Transaction has descendants in the wallet", rbf_node.bumpfee, parent_id)
|
||||||
|
# Now abandon the child transaction and bump the original
|
||||||
|
rbf_node.abandontransaction(child_id)
|
||||||
|
bumped_result = rbf_node.bumpfee(parent_id, {"fee_rate": HIGH})
|
||||||
|
assert bumped_result['txid'] in rbf_node.getrawmempool()
|
||||||
|
assert parent_id not in rbf_node.getrawmempool()
|
||||||
|
# Cleanup
|
||||||
|
self.restart_node(1, self.extra_args[1])
|
||||||
|
rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
|
||||||
|
self.connect_nodes(1, 0)
|
||||||
|
self.clear_mempool()
|
||||||
|
|
||||||
|
|
||||||
def test_small_output_with_feerate_succeeds(self, rbf_node, dest_address):
|
def test_small_output_with_feerate_succeeds(self, rbf_node, dest_address):
|
||||||
self.log.info('Testing small output with feerate bump succeeds')
|
self.log.info('Testing small output with feerate bump succeeds')
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue