Skip to content

Commit c49ce57

Browse files
committed
Add a new ChannelMoniorUpdateStep::ReleasePaymentComplete
`MonitorEvent`s aren't delivered to the `ChannelManager` in a durable fasion - if the `ChannelManager` fetches the pending `MonitorEvent`s, then the `ChannelMonitor` gets persisted (i.e. due to a block update) then the node crashes, prior to persisting the `ChannelManager` again, the `MonitorEvent` and its effects on the `ChannelManger` will be lost. This isn't likely in a sync persist environment, but in an async one this could be an issue. Note that this is only an issue for closed channels - `MonitorEvent`s only inform the `ChannelManager` that a channel is closed (which the `ChannelManager` will learn on startup or when it next tries to advance the channel state), that `ChannelMonitorUpdate` writes completed (which the `ChannelManager` will detect on startup), or that HTLCs resolved on-chain post closure. Of the three, only the last is problematic to lose prior to a reload. In previous commits we ensured that HTLC resolutions which came to `ChannelManager` via a `MonitorEvent` were replayed on startup if the `MonitorEvent` was lost. However, in cases where the `ChannelManager` was so stale that it didn't have the payment state for an HTLC at all, we only re-add it in cases where `ChannelMonitor::get_pending_or_resolved_outbound_htlcs` includes it. Because constantly re-adding a payment state and then failing it would generate lots of noise for users on startup (not to mention risk of confusing stale payment events for the latest state of a payment when the `PaymentId` has been reused to retry a payment). Thus, `get_pending_or_resolved_outbound_htlcs` does not include state for HTLCs which were resolved on chain with a preimage or HTLCs which were resolved on chain with a timeout after `ANTI_REORG_DELAY` confirmations. This critera matches the critera for generating a `MonitorEvent`, and works great under the assumption that `MonitorEvent`s are reliably delivered. However, if they are not, and our `ChannelManager` is lost or substantially old (or, in a future where we do not persist `ChannelManager` at all), we will not end up seeing payment resolution events for an HTLC. Instead, we really want to tell our `ChannelMonitor`s when the resolution of an HTLC is complete. Note that we don't particularly care about non-payment HTLCs, as there is no re-hydration of state to do there - `ChannelManager` load ignores forwarded HTLCs coming back from `get_pending_or_resolved_outbound_htlcs` as there's nothing to do - we always attempt to replay the success/failure and figure out if it mattered based on whether there was still an HTLC to claim/fail. Here we take the first step towards that notification, adding a new `ChannelMonitorUpdateStep` for the completion notification, and tracking HTLCs which make it to the `ChannelMonitor` in such updates in a new map.
1 parent d16e65d commit c49ce57

File tree

1 file changed

+40
-3
lines changed

1 file changed

+40
-3
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,20 @@ pub(crate) enum ChannelMonitorUpdateStep {
693693
RenegotiatedFundingLocked {
694694
funding_txid: Txid,
695695
},
696+
/// When a payment is finally resolved by the user handling an [`Event::PaymentSent`] or
697+
/// [`Event::PaymentFailed`] event, the `ChannelManager` no longer needs to hear about it on
698+
/// startup (which would cause it to re-hydrate the payment information even though the user
699+
/// already learned about the payment's result).
700+
///
701+
/// This will remove the HTLC from [`ChannelMonitor::get_all_current_outbound_htlcs`] and
702+
/// [`ChannelMonitor::get_onchain_failed_outbound_htlcs`].
703+
///
704+
/// Note that this is only generated for closed channels as this is implicit in the
705+
/// [`Self::CommitmentSecret`] update which clears the payment information from all un-revoked
706+
/// counterparty commitment transactions.
707+
ReleasePaymentComplete {
708+
htlc: SentHTLCId,
709+
},
696710
}
697711

698712
impl ChannelMonitorUpdateStep {
@@ -709,6 +723,7 @@ impl ChannelMonitorUpdateStep {
709723
ChannelMonitorUpdateStep::ShutdownScript { .. } => "ShutdownScript",
710724
ChannelMonitorUpdateStep::RenegotiatedFunding { .. } => "RenegotiatedFunding",
711725
ChannelMonitorUpdateStep::RenegotiatedFundingLocked { .. } => "RenegotiatedFundingLocked",
726+
ChannelMonitorUpdateStep::ReleasePaymentComplete { .. } => "ReleasePaymentComplete",
712727
}
713728
}
714729
}
@@ -747,6 +762,9 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
747762
(1, commitment_txs, required_vec),
748763
(3, htlc_data, required),
749764
},
765+
(7, ReleasePaymentComplete) => {
766+
(1, htlc, required),
767+
},
750768
(8, LatestHolderCommitment) => {
751769
(1, commitment_txs, required_vec),
752770
(3, htlc_data, required),
@@ -1250,6 +1268,14 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
12501268
/// spending CSV for revocable outputs).
12511269
htlcs_resolved_on_chain: Vec<IrrevocablyResolvedHTLC>,
12521270

1271+
/// When a payment is resolved through an on-chain transaction, we tell the `ChannelManager`
1272+
/// about this via [`ChannelMonitor::get_onchain_failed_outbound_htlcs`] and
1273+
/// [`ChannelMonitor::get_all_current_outbound_htlcs`] at startup. We'll keep repeating the
1274+
/// same payments until they're eventually fully resolved by the user processing a
1275+
/// `PaymentSent` or `PaymentFailed` event, at which point the `ChannelManager` will inform of
1276+
/// this and we'll store the set of fully resolved payments here.
1277+
htlcs_resolved_to_user: HashSet<SentHTLCId>,
1278+
12531279
/// The set of `SpendableOutput` events which we have already passed upstream to be claimed.
12541280
/// These are tracked explicitly to ensure that we don't generate the same events redundantly
12551281
/// if users duplicatively confirm old transactions. Specifically for transactions claiming a
@@ -1654,6 +1680,7 @@ pub(crate) fn write_chanmon_internal<Signer: EcdsaChannelSigner, W: Writer>(
16541680
(29, channel_monitor.initial_counterparty_commitment_tx, option),
16551681
(31, channel_monitor.funding.channel_parameters, required),
16561682
(32, channel_monitor.pending_funding, optional_vec),
1683+
(33, channel_monitor.htlcs_resolved_to_user, required),
16571684
(34, channel_monitor.alternative_funding_confirmed, option),
16581685
});
16591686

@@ -1872,6 +1899,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
18721899
funding_spend_confirmed: None,
18731900
confirmed_commitment_tx_counterparty_output: None,
18741901
htlcs_resolved_on_chain: Vec::new(),
1902+
htlcs_resolved_to_user: new_hash_set(),
18751903
spendable_txids_confirmed: Vec::new(),
18761904

18771905
best_block,
@@ -4218,6 +4246,10 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
42184246
panic!("Attempted to replace shutdown script {} with {}", shutdown_script, scriptpubkey);
42194247
}
42204248
},
4249+
ChannelMonitorUpdateStep::ReleasePaymentComplete { htlc } => {
4250+
log_trace!(logger, "HTLC {htlc:?} permanently and fully resolved");
4251+
self.htlcs_resolved_to_user.insert(*htlc);
4252+
},
42214253
}
42224254
}
42234255

@@ -4243,11 +4275,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
42434275
|ChannelMonitorUpdateStep::RenegotiatedFundingLocked { .. } =>
42444276
is_pre_close_update = true,
42454277
// After a channel is closed, we don't communicate with our peer about it, so the
4246-
// only things we will update is getting a new preimage (from a different channel)
4247-
// or being told that the channel is closed. All other updates are generated while
4248-
// talking to our peer.
4278+
// only things we will update is getting a new preimage (from a different channel),
4279+
// being told that the channel is closed, or being told a payment which was
4280+
// resolved on-chain has had its resolution communicated to the user. All other
4281+
// updates are generated while talking to our peer.
42494282
ChannelMonitorUpdateStep::PaymentPreimage { .. } => {},
42504283
ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {},
4284+
ChannelMonitorUpdateStep::ReleasePaymentComplete { .. } => {},
42514285
}
42524286
}
42534287

@@ -6324,6 +6358,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
63246358

63256359
let mut funding_spend_confirmed = None;
63266360
let mut htlcs_resolved_on_chain = Some(Vec::new());
6361+
let mut htlcs_resolved_to_user = Some(new_hash_set());
63276362
let mut funding_spend_seen = Some(false);
63286363
let mut counterparty_node_id = None;
63296364
let mut confirmed_commitment_tx_counterparty_output = None;
@@ -6357,6 +6392,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
63576392
(29, initial_counterparty_commitment_tx, option),
63586393
(31, channel_parameters, (option: ReadableArgs, None)),
63596394
(32, pending_funding, optional_vec),
6395+
(33, htlcs_resolved_to_user, option),
63606396
(34, alternative_funding_confirmed, option),
63616397
});
63626398
if let Some(payment_preimages_with_info) = payment_preimages_with_info {
@@ -6516,6 +6552,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
65166552
funding_spend_confirmed,
65176553
confirmed_commitment_tx_counterparty_output,
65186554
htlcs_resolved_on_chain: htlcs_resolved_on_chain.unwrap(),
6555+
htlcs_resolved_to_user: htlcs_resolved_to_user.unwrap(),
65196556
spendable_txids_confirmed: spendable_txids_confirmed.unwrap(),
65206557

65216558
best_block,

0 commit comments

Comments
 (0)