poller: unspend coins before spending new

This change ensures that the spend txid of a coin is updated
directly to another value in case a conflicting spend is
detected.

The previous order caused the spend txid to first be cleared,
which would misleadingly make the coin appear as confirmed
rather than spending.
This commit is contained in:
jp1ac4 2024-02-08 12:47:00 +00:00
parent 1e7653e08a
commit cc1de1d6d6
No known key found for this signature in database
GPG Key ID: A7ACD32423568D7B
2 changed files with 21 additions and 6 deletions

View File

@ -245,8 +245,8 @@ fn updates(
db_conn.new_unspent_coins(&updated_coins.received);
db_conn.remove_coins(&updated_coins.expired);
db_conn.confirm_coins(&updated_coins.confirmed);
db_conn.spend_coins(&updated_coins.spending);
db_conn.unspend_coins(&updated_coins.expired_spending);
db_conn.spend_coins(&updated_coins.spending);
db_conn.confirm_spend(&updated_coins.spent);
if latest_tip != current_tip {
db_conn.update_tip(&latest_tip);

View File

@ -3,6 +3,7 @@ import copy
from fixtures import *
from test_framework.utils import (
wait_for,
wait_for_while_condition_holds,
get_txid,
spend_coins,
RpcError,
@ -407,7 +408,13 @@ def test_conflicting_unconfirmed_spend_txs(lianad, bitcoind):
return False
return coin["spend_info"]["txid"] == txid.hex()
wait_for(lambda: is_spent_by(lianad, spent_coin["outpoint"], txid_b))
wait_for_while_condition_holds(
lambda: is_spent_by(lianad, spent_coin["outpoint"], txid_b),
lambda: lianad.rpc.listcoins([], [spent_coin["outpoint"]])["coins"][0][
"spend_info"
]
is not None, # The spend txid changes directly from txid_a to txid_b
)
def test_spend_replacement(lianad, bitcoind):
@ -454,11 +461,15 @@ def test_spend_replacement(lianad, bitcoind):
# newly marked as spending, the second one's spend_txid should be updated and
# the first one's spend txid should be dropped.
second_txid = sign_and_broadcast_psbt(lianad, second_psbt)
wait_for(
wait_for_while_condition_holds(
lambda: all(
c["spend_info"] is not None and c["spend_info"]["txid"] == second_txid
for c in lianad.rpc.listcoins([], second_outpoints)["coins"]
)
),
lambda: lianad.rpc.listcoins([], [coins[1]["outpoint"]])["coins"][0][
"spend_info"
]
is not None, # The spend txid of coin from first spend is updated directly
)
wait_for(
lambda: lianad.rpc.listcoins([], [first_outpoints[0]])["coins"][0]["spend_info"]
@ -467,11 +478,15 @@ def test_spend_replacement(lianad, bitcoind):
# Now RBF the second transaction with a send-to-self, just because.
third_txid = sign_and_broadcast_psbt(lianad, third_psbt)
wait_for(
wait_for_while_condition_holds(
lambda: all(
c["spend_info"] is not None and c["spend_info"]["txid"] == third_txid
for c in lianad.rpc.listcoins([], second_outpoints)["coins"]
)
),
lambda: all(
c["spend_info"] is not None
for c in lianad.rpc.listcoins([], second_outpoints)["coins"]
), # The spend txid of all coins are updated directly
)
assert (
lianad.rpc.listcoins([], [first_outpoints[0]])["coins"][0]["spend_info"] is None