Check in-flight monitor updates in force_shutdown for LocalAnnounced HTLCs#4434
Conversation
|
👋 Thanks for assigning @TheBlueMatt as a reviewer! |
2d36c03 to
cce8ccb
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4434 +/- ##
==========================================
+ Coverage 85.93% 85.97% +0.03%
==========================================
Files 159 159
Lines 104693 104712 +19
Branches 104693 104712 +19
==========================================
+ Hits 89972 90022 +50
+ Misses 12213 12187 -26
+ Partials 2508 2503 -5
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
lightning/src/ln/channelmanager.rs
Outdated
| chan.force_shutdown(reason) | ||
| let in_flight = in_flight_monitor_updates | ||
| .get(&chan_id) | ||
| .map(|(_, updates)| updates.iter().collect::<Vec<_>>()) |
There was a problem hiding this comment.
Do we really need this allocation? Can we just pass the iterator to force_shutdown instead?
|
👋 The first review has been submitted! Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer. |
cce8ccb to
ad3036e
Compare
TheBlueMatt
left a comment
There was a problem hiding this comment.
Hmmmmmmmmm, its really not quite so simple. If a monitor update is InProgress we generally expect the in-memory ChannelMonitor to have actually seen the new state update (though we expect that on restart there's a good chance it won't have that information and it'll be replayed). That means the monitor is theoretically "in charge" of resolving the HTLCs in question. While I think this patch is correct, I'm a bit hesitant to end up with two things in charge of resolving a specific HTLC. ISTM it also wouldn't be so complicated to immediately mark HTLCs as failed in the monitor upon receiving updates that try to add new HTLCs after a channel has been closed.
Isn't the problem with this that the monitor can't see whether the commitment was already sent to the peer or blocked by async persistence? |
|
Right, the monitor has to assume it may have been sent to the peer. That's fine, though, it should be able to fail the HTLC(s) once the commitment transaction is locked. |
|
Hmm, it seems that the original issue isn't an issue then. I confirmed that mining the force close commitment tx indeed generates the payment failed event. Or is there still something missing? |
|
In the general case ( |
|
The one that I identified wasn't a crash case. An assertion in the fuzzer identified that a payment was lost, but with current understanding I think it's just that the fuzzer didn't push the force-close forward enough (mine). Will close it for now and can look again if the payment remains lost even with confirmation of the commit tx. Unit test did confirm that it should just work. |
|
Reopening as this fix is now required for #4351. |
Now that we've decided that for deferred writes we no longer want to expect the in-memory |
| if let OutboundHTLCState::LocalAnnounced(_) = htlc.state { | ||
| for update in self.blocked_monitor_updates.iter() { | ||
| for update in update.update.updates.iter() { | ||
| let blocked_iter = self.blocked_monitor_updates.iter().map(|u| &u.update); |
There was a problem hiding this comment.
I do wonder if it is also possible for outbound htlcs to have already progressed to the Committed or later states? In that case, we might also want to catch that here.
6421a28 to
8dac2fa
Compare
| events.pop().unwrap(), | ||
| Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } | ||
| )); | ||
| expect_payment_failed_conditions_event( |
There was a problem hiding this comment.
This now no longer needs to wait for the force close to confirm.
…HTLCs When building dropped_outbound_htlcs during force_shutdown, LocalAnnounced HTLCs were only checked against blocked_monitor_updates. This relied on the implicit contract that in-progress monitor updates have always been applied to the in-memory ChannelMonitor already. If InProgress is returned without the monitor knowing about the update yet, the HTLC is silently dropped with no PaymentPathFailed or PaymentFailed event generated. Pass the in-flight monitor updates for the channel into force_shutdown so both blocked and in-flight updates are checked. This ensures LocalAnnounced HTLCs whose monitor updates have not yet been applied are properly included in dropped_outbound_htlcs and failed back to the sender. Closes lightningdevkit#4431 AI tools were used in preparing this commit.
8dac2fa to
da66b8e
Compare
TheBlueMatt
left a comment
There was a problem hiding this comment.
Now that we've decided that for deferred writes we no longer want to expect the in-memory ChannelMonitor to have seen the changes, I think the above doesn't apply anymore, and we might have to accept that two things are in charge for resolving a specific HTLC.
I don't think so. Instead, what we'll need to do is detect a new local counterparty state ChannelMontiorUpdate after the channel has close and track it to fail the HTLCs from it once the commitment transaction has 6 confs.
|
Oh actually no I don't think we need to wait for 6 confs since we never sent the message, ie we can fail it immediately. |
Closes #4431