client/core,asset: ensure coins are unlocked when no longer needed#648
Conversation
d7c8ef1 to
ebc41b9
Compare
|
After #513 is done and you're back to this one, can you call out any clearly-neglected coin locking sites are fixed? There's a lot of refactoring here, so it's hard to get an idea of which specific cases are resolved. |
|
Called that out in the PR description but was probably not clear. I've edited the description.
Will recheck to confirm I haven't missed any, but last I checked, those were it. |
|
To simplify this, we can allow some cases to fall back to unlocking, possibly redundantly, on retirement of trackedTrades. #665 Perhaps we can simplify the approach in this PR considerably to focus on the low-hanging fruit that does not require unbook ntfn tricks. |
5a2fd10 to
3bfb72d
Compare
Makes sense. To further simplify, we can make trade retirement the sole point of coin unlocking - only unlock coins when the associated trade/order is retired. The only caveat I see there is some trade coins will remain locked for longer if a trade is kept alive simply for refund or auto-redeem reasons, as those recovery actions may take a while. We could ofc unlock coins for such orders (while not retiring them) and set If you're okay with having all coin unlocking done from the site of trade retirement, will you want to take that up in #665 or should I pull in your #665 commits and finish up here? |
I'm pretty sure that would break things. Most importantly, it would prevent someone from using remaining funds from a canceled, but partially filled order until all matches are fully negotiated. Let's roll with this PR as is. |
|
A breakdown of ideal coin-unlocking sites, particularly important with commit 48b0e22 stopping coin unlocking on client shutdown. Checked checkboxes with no link to implementation are implemented in this PR. Orders for which coins should be unlocked:
All other orders that receive one or more matches have no further use for locked coins when they're
The following are cases where coins will remain needlessly locked, and resolution measures to ensure the coins are unlocked as required:
|
Coins are currently unlocked when - a market order or limit order with tif immediate does not get matched - an order is canceled (i.e. by user action) - a market is suspended with persist=false Other times to unlock coins: - when new orders could not be submitted to the server, e.g. if sending the request or validating the server's response fails. - when all matches are either swapped or revoked for unbooked orders, i.e. orders that will not receive future matches. - after sending a swap, unlock the spent outputs to ensure accurate balance reporting.
Also, update docs for btc.Swap and dcr.Swap to indicate the need (or lack of) to manually unlock input coins after broadcasting swap tx.
- Exclude revoked matches when determining last swaps. - Don't override t.changeLocked until swaps are successfully sent.
Setting the matches as revoked is insufficient as locked coins will not be returned unless some other action triggers coin unlocking e.g. swapMatches(). If the affected trade is Executed, Revoked or Canceled and has no swap-pending match, any locked coins will remain locked.
Keeping coins locked ensures that they're not spent by the wallet while the client is shutdown.
0d5e1fc to
6e8402c
Compare
|
I'm okay with merging this, leaving further coin unlocking work for the implementation of order status recovery described in #597 (comment). Is there any merit to temporarily restoring coin unlocking on asset shutdown? Most of those coins will be relocked on client restart, except coins for
In summary, I don't think client shutdown should be the trigger for unlocking coins. Only unlock coins when they're no longer needed, falling back to unlocking coins when trades are retired. As long as the client considers a trade active, the associated coins should remain locked. I'm probably gonna want to move the client coin unlocking requirement described in #648 (comment) to an issue to ensure coins don't stay locked against expectations. |
| // Do NOT unlock the coins because the request may have actually reached | ||
| // the server. | ||
| return nil, 0, fmt.Errorf("new order request with DEX server %v failed: %w", dc.acct.host, err) |
There was a problem hiding this comment.
I'm reconsidering this. The client does not save the order to db, nor will it respond to preimage requests for the order. Only advantage to keeping the coins locked is to prevent new orders from using these coins as they're already locked by the server. But we can't keep these locked forever. And there's no client-restart-agnostic reliable way of knowing that the server has also ditched the order, so we can safely unlock coins.
Any objections to unlocking right away?
There was a problem hiding this comment.
This is an odd case. It's hard to imagine the request failing but it actually being booked, but if the client cannot do anything with the order, I don't see a reason to keep the coins locked.
Coins are currently unlocked when
Other times to unlock coins (implemented in this PR):
request or validating the server's response fails.
orders that will not receive future matches.
reporting.
Also revoke orders in UnbookOrder note handler to ensure that coins areunlocked for server-revoked orders. If such orders remain at status Booked,
their coins will never be unlocked because the expectation would be that the
order would receive new matches in the future.
UPDATE: As @chappjc pointed out, revoking orders in the UnbookOrder note
handler is a hack at best, and not a very good one. The client currently has no
way of detecting revoked orders; with the implication that coins for such orders
will remain perpetually locked.
Resolves #631.