bitcoin: drop spend txid for coins whose spending tx gets RBF'd
Even if the RBF does not spend this coin anymore.
This commit is contained in:
parent
544167dee4
commit
cf7c4fbac9
@ -269,28 +269,36 @@ impl BitcoinInterface for d::BitcoinD {
|
||||
|
||||
// If a conflicting transaction was confirmed instead, replace the txid of the
|
||||
// spender for this coin with it and mark it as confirmed.
|
||||
// If a conflicting transaction which doesn't spend this coin was mined or accepted in
|
||||
// our local mempool, mark this spend as expired.
|
||||
enum Conflict {
|
||||
// A replacement spending transaction was confirmed.
|
||||
Replaced((bitcoin::Txid, Block)),
|
||||
// A transaction conflicting with the former spending transaction was confirmed,
|
||||
// but it doesn't spend this outpoint anymore.
|
||||
// A transaction conflicting with the former spending transaction was confirmed or
|
||||
// included in our local mempool.
|
||||
Dropped,
|
||||
}
|
||||
let conflict = res.conflicting_txs.iter().find_map(|txid| {
|
||||
tx_getter.get_transaction(txid).and_then(|tx| {
|
||||
// FIXME: if a conflict was mined we should somehow wipe the spend_txid of this
|
||||
// coin.
|
||||
tx.block.map(|block| {
|
||||
// Being part of our watchonly wallet isn't enough, as it could be a
|
||||
// conflicting transaction which spends a different set of coins. Make sure
|
||||
// it does actually spend this coin.
|
||||
for txin in tx.tx.input {
|
||||
if &txin.previous_output == op {
|
||||
return Conflict::Replaced((*txid, block));
|
||||
tx.block
|
||||
.map(|block| {
|
||||
// Being part of our watchonly wallet isn't enough, as it could be a
|
||||
// conflicting transaction which spends a different set of coins. Make sure
|
||||
// it does actually spend this coin.
|
||||
for txin in tx.tx.input {
|
||||
if &txin.previous_output == op {
|
||||
return Conflict::Replaced((*txid, block));
|
||||
}
|
||||
}
|
||||
}
|
||||
Conflict::Dropped
|
||||
})
|
||||
Conflict::Dropped
|
||||
})
|
||||
.or_else(|| {
|
||||
if self.is_in_mempool(txid) {
|
||||
Some(Conflict::Dropped)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
match conflict {
|
||||
|
||||
@ -454,7 +454,7 @@ def test_spend_replacement(lianad, bitcoind):
|
||||
|
||||
# Now RBF the first transaction by the second one. The third coin should be
|
||||
# newly marked as spending, the second one's spend_txid should be updated and
|
||||
# the first one should not be updated until the second one is mined.
|
||||
# the first one's spend txid should be dropped.
|
||||
second_txid = sign_and_broadcast_psbt(lianad, second_psbt)
|
||||
wait_for(
|
||||
lambda: all(
|
||||
@ -462,9 +462,9 @@ def test_spend_replacement(lianad, bitcoind):
|
||||
for c in lianad.rpc.listcoins([], second_outpoints)["coins"]
|
||||
)
|
||||
)
|
||||
assert (
|
||||
lianad.rpc.listcoins([], [first_outpoints[0]])["coins"][0]["spend_info"]["txid"]
|
||||
== first_txid
|
||||
wait_for(
|
||||
lambda: lianad.rpc.listcoins([], [first_outpoints[0]])["coins"][0]["spend_info"]
|
||||
is None
|
||||
)
|
||||
|
||||
# Now RBF the second transaction with a send-to-self, just because.
|
||||
@ -476,11 +476,10 @@ def test_spend_replacement(lianad, bitcoind):
|
||||
)
|
||||
)
|
||||
assert (
|
||||
lianad.rpc.listcoins([], [first_outpoints[0]])["coins"][0]["spend_info"]["txid"]
|
||||
== first_txid
|
||||
lianad.rpc.listcoins([], [first_outpoints[0]])["coins"][0]["spend_info"] is None
|
||||
)
|
||||
|
||||
# Once the RBF gets mined, the first coin's spend txid is wiped.
|
||||
# Once the RBF is mined, we detect it as confirmed and the first coin is still unspent.
|
||||
bitcoind.generate_block(1, wait_for_mempool=third_txid)
|
||||
wait_for(
|
||||
lambda: all(
|
||||
@ -488,7 +487,6 @@ def test_spend_replacement(lianad, bitcoind):
|
||||
for c in lianad.rpc.listcoins([], second_outpoints)["coins"]
|
||||
)
|
||||
)
|
||||
wait_for(
|
||||
lambda: lianad.rpc.listcoins([], [first_outpoints[0]])["coins"][0]["spend_info"]
|
||||
is None
|
||||
assert (
|
||||
lianad.rpc.listcoins([], [first_outpoints[0]])["coins"][0]["spend_info"] is None
|
||||
)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user