Skip to content

Improve on (potentially) blocking wallet behaviors - #281

Merged
tnull merged 13 commits into
lightningdevkit:mainfrom
tnull:2024-04-improve-on-wallet-friction
Jun 20, 2024
Merged

Improve on (potentially) blocking wallet behaviors#281
tnull merged 13 commits into
lightningdevkit:mainfrom
tnull:2024-04-improve-on-wallet-friction

Conversation

@tnull

@tnulltnull commented Apr 12, 2024

Copy link
Copy Markdown
Collaborator

Based on #141.

Due to our onchain wallet requiring us to hold a Mutex for the duration of the chain sync, many operations might be blocked for seconds at at time.

Here, we make several changes that hopefully alleviate any blocking issues from holding the wallet lock(s). In particular we introduce a balance cache, drop our 'immediate retry sync' logic and drop the previous wallet_lockCondvar in favor of a pub/sub pattern that is beneficial in async runtime environments.

@tnull
tnullforce-pushed the 2024-04-improve-on-wallet-friction branch from 3d70262 to c0f13bcCompareApril 12, 2024 13:00
@tnulltnull changed the title Improve on wallet (potentially) blocking wallet behaviorsImprove on (potentially) blocking wallet behaviorsApr 12, 2024
@tnull
tnullforce-pushed the 2024-04-improve-on-wallet-friction branch 13 times, most recently from 8edbac9 to d4649e8CompareMay 17, 2024 12:42
This was referenced May 20, 2024
@tnulltnull added this to the 0.3 milestone May 20, 2024
@tnull
tnullforce-pushed the 2024-04-improve-on-wallet-friction branch from d4649e8 to abb6926CompareJune 1, 2024 07:57
@tnull

tnull commented Jun 1, 2024

Copy link
Copy Markdown
CollaboratorAuthor

Rebased on #141 to resolve minor conflicts with main.

@tnulltnull mentioned this pull request Jun 11, 2024
@tnull
tnullforce-pushed the 2024-04-improve-on-wallet-friction branch 2 times, most recently from 85affcf to 4abd601CompareJune 11, 2024 18:57
@tnull

Copy link
Copy Markdown
CollaboratorAuthor

Rebased on main after #141 landed.

@tnull
tnull requested a review from jkczyzJune 11, 2024 19:02
@tnull
tnullforce-pushed the 2024-04-improve-on-wallet-friction branch from 4abd601 to fa7690bCompareJune 14, 2024 07:27
@tnull

Copy link
Copy Markdown
CollaboratorAuthor

Rebased after #307 landed.

@jbesraajbesraa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this branch locally with an app with GUI that previously lagged when the wallet synced and I can confirm that with this PR things are much smoother

@tnull

tnull commented Jun 14, 2024

Copy link
Copy Markdown
CollaboratorAuthor

I tested this branch locally with an app with GUI that previously lagged when the wallet synced and I can confirm that with this PR things are much smoother

Yeah, without these workarounds the post-Anchors code is borderline unusable as event handling might grind to a standstill whenever we need to check the balance and wallet syncing is ongoing.

@tnull
tnullforce-pushed the 2024-04-improve-on-wallet-friction branch from fa7690b to 840ca4fCompareJune 17, 2024 07:35
@tnull

Copy link
Copy Markdown
CollaboratorAuthor

Rebased to resolve minor conflict after #303 landed.

@tnull
tnullforce-pushed the 2024-04-improve-on-wallet-friction branch from 840ca4f to a85fedeCompareJune 18, 2024 09:15
@tnull

tnull commented Jun 18, 2024

Copy link
Copy Markdown
CollaboratorAuthor

Now also added a commit dropping the immediate-retry behavior in TxBroadcaster, and applying the timeout to tx_sync.sync() in sync_wallets

@tnull
tnullforce-pushed the 2024-04-improve-on-wallet-friction branch 2 times, most recently from c1ff7a1 to 0e9cacaCompareJune 18, 2024 13:06
@tnull
tnull requested a review from G8XSUJune 18, 2024 17:58
Comment threadsrc/wallet.rs
*self.balance_cache.write().unwrap() = balance.clone();
balance
},
Err(_) => self.balance_cache.read().unwrap().clone(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you expand on some of the implications of using a cached balance ?

iiuc, we might bypass some of the balance checks during open-channel (outbound and inbound) and send_to_address.(does bdk allow building tx greater than balance?)

@tnulltnullJun 19, 2024

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you expand on some of the implications of using a cached balance ?

It essentially has no implications: generally the wallet balance would always just be updated when a sync succeeds and here we make sure to always update the cache afterwards, while still holding the wallet Mutex. So the cache should always be up to date. Plus, we'll actually call through and update the cache whenever we can.

iiuc, we might bypass some of the balance checks during open-channel (outbound and inbound) and send_to_address.(does bdk allow building tx greater than balance?)

Yes, but IIUC BDK's wallet would always only pick up on any changes after a successful sync, i.e., it would show the old balance anyways.

Btw, see relatedly: #41

Comment threadsrc/wallet.rs
@@ -175,13 +199,24 @@ where
pub(crate) fn get_balances(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be worth to add doc that result might be cached.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly don't think it matters: a) this is pub(crate), and b) it shouldn't result in any noticeable behavior changes, as discussed above.

Comment threadsrc/wallet.rs Outdated
bdk::Error::Esplora(ref be) => match **be {
bdk::blockchain::esplora::EsploraError::Reqwest(_) => {
// Drop lock, sleep for a second, retry.
drop(wallet_lock);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we this and retry here, only to remove it in later commit, can be simplified if we just drop retry before this.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. Are you fine with me leaving it like this or would you prefer to invert the commit ordering?

Comment threadsrc/wallet.rs Outdated
Comment threadsrc/wallet.rs Outdated
Comment threadsrc/wallet.rs Outdated
@tnull
tnullforce-pushed the 2024-04-improve-on-wallet-friction branch 2 times, most recently from afee329 to fcb824fCompareJune 20, 2024 16:39
@tnull

Copy link
Copy Markdown
CollaboratorAuthor

Kicked CI.

@G8XSU Let me know if I can squash the fixups.

@G8XSU

Copy link
Copy Markdown
Contributor

Lgtm!
feel free to squash fixups.

tnull added 13 commits June 20, 2024 19:10
Unfortunately BDK's current wallet design requires us to have it live in `Mutex`
that is locked for long periods of time during syncing. This is
especially painful for short-lived operations that just operate locally,
such as retrieving the current balance, which we now do in several
places to be able to check Anchor channels limitations, e.g., in event
handling.
In order to avoid blocking during balance retrieval, we introduce a
`balance` cache that will be refreshed whenever we're done with syncing
*or* when we can successfully get the wallet lock. Otherwise, we'll just
return the cached value, allowing us to make progress even though a
background sync of the wallet might be in-progress.
Using a `Condvar` could be potentially dangerous in async contexts as
`wait`ing on it might block the current thread potentially hosting more
than one task. Here, we drop the `Condvar` and adopt a pub/sub scheme
instead, similar to the one we already implemented in
`ConnectionManager`.
It's not super clear that it achieves much in the face of a rate-limited
Esplora server, and having a custom sleep there is just awkward. So we
drop it and hope we still get a chance to sync our on-chain wallet now
and then.
.. as we're not sure it actually increases reliability.
We now only log failures, ignoring HTTP 400 as this is bitcoind's error
code for "transaction already in mempool".
.. to make progress and unblock the `Mutex` even if BDK's wallet `sync` would never return.
.. even though we don't expect this to block, we're better safe than
sorry and start to introduce timeouts for any calls we make to remote
servers.
.. even though we don't expect this to block, we're better safe than
sorry and start to introduce timeouts for any calls we make to remote
servers.
.. even though we don't expect this to block, we're better safe than
sorry and start to introduce timeouts for any calls we make to remote
servers.
.. before initiating the Runtime shutdown.
.. as we use `Clone` for `tokio::sync::watch::Sender`, which was only
introduced with 1.37.
@tnull
tnullforce-pushed the 2024-04-improve-on-wallet-friction branch from fcb824f to f839015CompareJune 20, 2024 17:10
@tnull

Copy link
Copy Markdown
CollaboratorAuthor

Lgtm! feel free to squash fixups.

Squashed without further changes.

@tnull
tnull merged commit ca44721 into lightningdevkit:mainJun 20, 2024
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@tnull@G8XSU@jbesraa