-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
poller: unspend expired before new spend #965
poller: unspend expired before new spend #965
Conversation
6a4967c
to
8c7fec7
Compare
Refactored the new utils function. |
8c7fec7
to
eb36a23
Compare
Rebased on master. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rationale for this ordering is to make sure a coin marked as spending in this round which then gets marked as expired does get recorded correctly.
This is because we check the spend status of both the coins marked spending in DB but also the newly spending coins:
liana/src/bitcoin/poller/looper.rs
Lines 136 to 146 in 147cc0b
// Mark coins in a spending state whose Spend transaction was confirmed as such. Note we | |
// need to take into account the freshly marked as spending coins as well, as their spend | |
// may have been confirmed within the previous tip and the current one, and we may not poll | |
// this chunk of the chain anymore. | |
let spending_coins: Vec<(bitcoin::OutPoint, bitcoin::Txid)> = db_conn | |
.list_spending_coins() | |
.values() | |
.map(|coin| (coin.outpoint, coin.spend_txid.expect("Coin is spending"))) | |
.chain(spending.iter().cloned()) | |
.collect(); | |
let (spent, expired_spending) = bit.spent_coins(spending_coins.as_slice()); |
It seems this change could only cause issues in the unlikely scenario a coin gets detected as spending and "expires" right before we check its spend status in spent_coins
and therefore we miss it did expire. But in this case it would just be marked as such at the next polling round, that's fine.
tests/test_framework/utils.py
Outdated
@@ -46,6 +56,10 @@ def wait_for(success, timeout=TIMEOUT, debug_fn=None): | |||
interval = 5 | |||
if time.time() > start_time + timeout: | |||
raise ValueError("Error waiting for {}", success) | |||
if not condition(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's a bit fragile: it's possible for a caller to provide a condition
function such as it returns True
above and False
here during the second call. It would be more robust to change the loop above to be:
while True:
if success() or time >= start_time + timeout:
break
if condition():
raise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true. Perhaps we could also do:
while True:
if time.time() >= start_time + timeout:
raise
if not condition():
raise
if success():
return
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've now updated this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK. It does make a lot of sense, i think that's a bugfix and is harmless. I'd like to sleep on it though.
In a followup it would be worthwile to introduce this new |
This adds a new utils function that is a slight generalisation of `wait_for` with an additional condition that must always be met while waiting. `wait_for` now calls this new function with the condition being one that is always true.
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.
eb36a23
to
cc1de1d
Compare
Updated |
ACK cc1de1d |
1c99376 gui(app): cache unconfirmed & confirmed coins only (jp1ac4) daf9f85 gui(spend): filter for unconfirmed & confirmed coins (jp1ac4) 982220d gui(home): filter for unconfirmed & confirmed coins (jp1ac4) 85b053f gui(recovery): filter for unconfirmed & confirmed coins (jp1ac4) c9fcfae gui(recovery): filter coins by psbt outpoints (jp1ac4) 4509bd6 gui(coins): filter for confirmed & unconfirmed (jp1ac4) 685f83b gui(transactions): remove unused list_coins (jp1ac4) 21f8704 gui(transactions): filter coins by tx outpoints (jp1ac4) ddd1e84 gui(psbt): get conflicting txs from filtered coins (jp1ac4) 4641d9e gui(daemon): filter coins using spend txs prev outpoints (jp1ac4) aa578ba gui(daemon): filter coins for pending txs (jp1ac4) 4612159 gui(daemon): filter outpoints from txs inputs & outputs (jp1ac4) f3fdb96 gui(daemon): extract common function for historytxs (jp1ac4) 6c7ca2c gui(daemon): add optional filter to `list_coins` (jp1ac4) Pull request description: This is to resolve #677. As well as adding the filters to the daemon interface, I've applied filters in separate commits to different sections of the GUI. This PR builds on changes from #958 and #965. The latter is required when filtering for pending transactions so that a coin whose spending txid changes (e.g. due to RBF) remains as spending. ACKs for top commit: edouardparis: ACK 1c99376 Tree-SHA512: c8b9c68a8344df1dbb04b22e315234dec7ae0c18bfc697f88296d3a4b5e7276a48005db6caf1a0b89a23e174f72118ad10945118be8cd96fbee20ba79c12d721
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.
I've added a new utils function for the functional tests that is a slight generalisation of
wait_for
with an additional condition that must always be met while waiting.wait_for
now calls this new function with the condition being one that is always true.