Skip to content

Commit d3ff670

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. Backport of c49ce57 Trivial conflicts resolved in: * lightning/src/chain/channelmonitor.rs
1 parent 1da1275 commit d3ff670

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
@@ -567,6 +567,20 @@ pub(crate) enum ChannelMonitorUpdateStep {
567567
ShutdownScript {
568568
scriptpubkey: ScriptBuf,
569569
},
570+
/// When a payment is finally resolved by the user handling an [`Event::PaymentSent`] or
571+
/// [`Event::PaymentFailed`] event, the `ChannelManager` no longer needs to hear about it on
572+
/// startup (which would cause it to re-hydrate the payment information even though the user
573+
/// already learned about the payment's result).
574+
///
575+
/// This will remove the HTLC from [`ChannelMonitor::get_all_current_outbound_htlcs`] and
576+
/// [`ChannelMonitor::get_onchain_failed_outbound_htlcs`].
577+
///
578+
/// Note that this is only generated for closed channels as this is implicit in the
579+
/// [`Self::CommitmentSecret`] update which clears the payment information from all un-revoked
580+
/// counterparty commitment transactions.
581+
ReleasePaymentComplete {
582+
htlc: SentHTLCId,
583+
},
570584
}
571585

572586
impl ChannelMonitorUpdateStep {
@@ -578,6 +592,7 @@ impl ChannelMonitorUpdateStep {
578592
ChannelMonitorUpdateStep::CommitmentSecret { .. } => "CommitmentSecret",
579593
ChannelMonitorUpdateStep::ChannelForceClosed { .. } => "ChannelForceClosed",
580594
ChannelMonitorUpdateStep::ShutdownScript { .. } => "ShutdownScript",
595+
ChannelMonitorUpdateStep::ReleasePaymentComplete { .. } => "ReleasePaymentComplete",
581596
}
582597
}
583598
}
@@ -612,6 +627,9 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
612627
(5, ShutdownScript) => {
613628
(0, scriptpubkey, required),
614629
},
630+
(7, ReleasePaymentComplete) => {
631+
(1, htlc, required),
632+
},
615633
);
616634

617635
/// Indicates whether the balance is derived from a cooperative close, a force-close
@@ -1000,6 +1018,14 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
10001018
/// spending CSV for revocable outputs).
10011019
htlcs_resolved_on_chain: Vec<IrrevocablyResolvedHTLC>,
10021020

1021+
/// When a payment is resolved through an on-chain transaction, we tell the `ChannelManager`
1022+
/// about this via [`ChannelMonitor::get_onchain_failed_outbound_htlcs`] and
1023+
/// [`ChannelMonitor::get_all_current_outbound_htlcs`] at startup. We'll keep repeating the
1024+
/// same payments until they're eventually fully resolved by the user processing a
1025+
/// `PaymentSent` or `PaymentFailed` event, at which point the `ChannelManager` will inform of
1026+
/// this and we'll store the set of fully resolved payments here.
1027+
htlcs_resolved_to_user: HashSet<SentHTLCId>,
1028+
10031029
/// The set of `SpendableOutput` events which we have already passed upstream to be claimed.
10041030
/// These are tracked explicitly to ensure that we don't generate the same events redundantly
10051031
/// if users duplicatively confirm old transactions. Specifically for transactions claiming a
@@ -1255,6 +1281,7 @@ impl<Signer: EcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signer> {
12551281
(21, self.balances_empty_height, option),
12561282
(23, self.holder_pays_commitment_tx_fee, option),
12571283
(25, self.payment_preimages, required),
1284+
(33, self.htlcs_resolved_to_user, required),
12581285
});
12591286

12601287
Ok(())
@@ -1458,6 +1485,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
14581485
funding_spend_confirmed: None,
14591486
confirmed_commitment_tx_counterparty_output: None,
14601487
htlcs_resolved_on_chain: Vec::new(),
1488+
htlcs_resolved_to_user: new_hash_set(),
14611489
spendable_txids_confirmed: Vec::new(),
14621490

14631491
best_block,
@@ -3402,6 +3430,10 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34023430
panic!("Attempted to replace shutdown script {} with {}", shutdown_script, scriptpubkey);
34033431
}
34043432
},
3433+
ChannelMonitorUpdateStep::ReleasePaymentComplete { htlc } => {
3434+
log_trace!(logger, "HTLC {htlc:?} permanently and fully resolved");
3435+
self.htlcs_resolved_to_user.insert(*htlc);
3436+
},
34053437
}
34063438
}
34073439

@@ -3423,11 +3455,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34233455
|ChannelMonitorUpdateStep::CommitmentSecret { .. } =>
34243456
is_pre_close_update = true,
34253457
// After a channel is closed, we don't communicate with our peer about it, so the
3426-
// only things we will update is getting a new preimage (from a different channel)
3427-
// or being told that the channel is closed. All other updates are generated while
3428-
// talking to our peer.
3458+
// only things we will update is getting a new preimage (from a different channel),
3459+
// being told that the channel is closed, or being told a payment which was
3460+
// resolved on-chain has had its resolution communicated to the user. All other
3461+
// updates are generated while talking to our peer.
34293462
ChannelMonitorUpdateStep::PaymentPreimage { .. } => {},
34303463
ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {},
3464+
ChannelMonitorUpdateStep::ReleasePaymentComplete { .. } => {},
34313465
}
34323466
}
34333467

@@ -5188,6 +5222,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
51885222

51895223
let mut funding_spend_confirmed = None;
51905224
let mut htlcs_resolved_on_chain = Some(Vec::new());
5225+
let mut htlcs_resolved_to_user = Some(new_hash_set());
51915226
let mut funding_spend_seen = Some(false);
51925227
let mut counterparty_node_id = None;
51935228
let mut confirmed_commitment_tx_counterparty_output = None;
@@ -5212,6 +5247,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
52125247
(21, balances_empty_height, option),
52135248
(23, holder_pays_commitment_tx_fee, option),
52145249
(25, payment_preimages_with_info, option),
5250+
(33, htlcs_resolved_to_user, option),
52155251
});
52165252
if let Some(payment_preimages_with_info) = payment_preimages_with_info {
52175253
if payment_preimages_with_info.len() != payment_preimages.len() {
@@ -5302,6 +5338,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
53025338
funding_spend_confirmed,
53035339
confirmed_commitment_tx_counterparty_output,
53045340
htlcs_resolved_on_chain: htlcs_resolved_on_chain.unwrap(),
5341+
htlcs_resolved_to_user: htlcs_resolved_to_user.unwrap(),
53055342
spendable_txids_confirmed: spendable_txids_confirmed.unwrap(),
53065343

53075344
best_block,

0 commit comments

Comments
 (0)