Skip to content

Commit 3bd1e41

Browse files
committed
Add an immediately-freeing MonitorUpdateCompletionAction.
When `MonitorUpdateCompletionAction`s were added, we didn't consider the case of a duplicate claim during normal HTLC processing (as the handling only had an `if let` rather than a `match`, which made the branch easy to miss). This can lead to a channel freezing indefinitely if an HTLC is claimed (without a `commitment_signed`), the peer disconnects, and then the HTLC is claimed again, leading to a never-completing `MonitorUpdateCompletionAction`. The fix is simple - if we get back an `UpdateFulfillCommitFetch::DuplicateClaim` when claiming from the inbound edge, immediately unlock the outbound edge channel with a new `MonitorUpdateCompletionAction::FreeOtherChannelImmediately`. Here we add the new variant, which we start generating in the next commit.
1 parent 03df441 commit 3bd1e41

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

lightning/src/ln/channelmanager.rs

+36
Original file line numberDiff line numberDiff line change
@@ -615,10 +615,34 @@ pub(crate) enum MonitorUpdateCompletionAction {
615615
event: events::Event,
616616
downstream_counterparty_and_funding_outpoint: Option<(PublicKey, OutPoint, RAAMonitorUpdateBlockingAction)>,
617617
},
618+
/// Indicates we should immediately resume the operation of another channel, unless there is
619+
/// some other reason why the channel is blocked. In practice this simply means immediately
620+
/// removing the [`RAAMonitorUpdateBlockingAction`] provided from the blocking set.
621+
///
622+
/// This is usually generated when we've forwarded an HTLC and want to block the outbound edge
623+
/// from completing a monitor update which removes the payment preimage until the inbound edge
624+
/// completes a monitor update containing the payment preimage. However, we use this variant
625+
/// instead of [`Self::EmitEventAndFreeOtherChannel`] when we discover that the claim was in
626+
/// fact duplicative and we simply want to resume the outbound edge channel immediately.
627+
///
628+
/// This variant should thus never be written to disk, as it is processed inline rather than
629+
/// stored for later processing.
630+
FreeOtherChannelImmediately {
631+
downstream_counterparty_node_id: PublicKey,
632+
downstream_funding_outpoint: OutPoint,
633+
blocking_action: RAAMonitorUpdateBlockingAction,
634+
},
618635
}
619636

620637
impl_writeable_tlv_based_enum_upgradable!(MonitorUpdateCompletionAction,
621638
(0, PaymentClaimed) => { (0, payment_hash, required) },
639+
// Note that FreeOtherChannelImmediately should never be written - we were supposed to free
640+
// *immediately*. However, for simplicity we implement read/write here.
641+
(1, FreeOtherChannelImmediately) => {
642+
(0, downstream_counterparty_node_id, required),
643+
(2, downstream_funding_outpoint, required),
644+
(4, blocking_action, required),
645+
},
622646
(2, EmitEventAndFreeOtherChannel) => {
623647
(0, event, upgradable_required),
624648
// LDK prior to 0.0.116 did not have this field as the monitor update application order was
@@ -5585,6 +5609,15 @@ where
55855609
self.handle_monitor_update_release(node_id, funding_outpoint, Some(blocker));
55865610
}
55875611
},
5612+
MonitorUpdateCompletionAction::FreeOtherChannelImmediately {
5613+
downstream_counterparty_node_id, downstream_funding_outpoint, blocking_action,
5614+
} => {
5615+
self.handle_monitor_update_release(
5616+
downstream_counterparty_node_id,
5617+
downstream_funding_outpoint,
5618+
Some(blocking_action),
5619+
);
5620+
},
55885621
}
55895622
}
55905623
}
@@ -9989,6 +10022,9 @@ where
998910022
// anymore.
999010023
}
999110024
}
10025+
if let MonitorUpdateCompletionAction::FreeOtherChannelImmediately { .. } = action {
10026+
debug_assert!(false, "Non-event-generating channel freeing should not appear in our queue");
10027+
}
999210028
}
999310029
}
999410030
peer_state.lock().unwrap().monitor_update_blocked_actions = monitor_update_blocked_actions;

0 commit comments

Comments
 (0)