Skip to content

Commit 94bce4a

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 658c408 commit 94bce4a

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,20 @@ pub(crate) enum ChannelMonitorUpdateStep {
681681
RenegotiatedFundingLocked {
682682
funding_txid: Txid,
683683
},
684+
/// When a payment is finally resolved by the user handling an [`Event::PaymentSent`] or
685+
/// [`Event::PaymentFailed`] event, the `ChannelManager` no longer needs to hear about it on
686+
/// startup (which would cause it to re-hydrate the payment information even though the user
687+
/// already learned about the payment's result).
688+
///
689+
/// This will remove the HTLC from [`ChannelMonitor::get_all_current_outbound_htlcs`] and
690+
/// [`ChannelMonitor::get_onchain_failed_outbound_htlcs`].
691+
///
692+
/// Note that this is only generated for closed channels as this is implicit in the
693+
/// [`Self::CommitmentSecret`] update which clears the payment information from all un-revoked
694+
/// counterparty commitment transactions.
695+
ReleasePaymentComplete {
696+
htlc: SentHTLCId,
697+
},
684698
}
685699

686700
impl ChannelMonitorUpdateStep {
@@ -697,6 +711,7 @@ impl ChannelMonitorUpdateStep {
697711
ChannelMonitorUpdateStep::ShutdownScript { .. } => "ShutdownScript",
698712
ChannelMonitorUpdateStep::RenegotiatedFunding { .. } => "RenegotiatedFunding",
699713
ChannelMonitorUpdateStep::RenegotiatedFundingLocked { .. } => "RenegotiatedFundingLocked",
714+
ChannelMonitorUpdateStep::ReleasePaymentComplete { .. } => "ReleasePaymentComplete",
700715
}
701716
}
702717
}
@@ -735,6 +750,9 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
735750
(1, commitment_txs, required_vec),
736751
(3, htlc_data, required),
737752
},
753+
(7, ReleasePaymentComplete) => {
754+
(1, htlc, required),
755+
},
738756
(8, LatestHolderCommitment) => {
739757
(1, commitment_txs, required_vec),
740758
(3, htlc_data, required),
@@ -1234,6 +1252,12 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
12341252
/// spending CSV for revocable outputs).
12351253
htlcs_resolved_on_chain: Vec<IrrevocablyResolvedHTLC>,
12361254

1255+
/// When a payment is fully resolved by the user processing a PaymentSent or PaymentFailed
1256+
/// event, we are informed by the ChannelManager (if the payment was resolved by an on-chain
1257+
/// transaction) of this so that we can stop telling the ChannelManager about the payment in
1258+
/// the future. We store the set of fully resolved payments here.
1259+
htlcs_resolved_to_user: HashSet<SentHTLCId>,
1260+
12371261
/// The set of `SpendableOutput` events which we have already passed upstream to be claimed.
12381262
/// These are tracked explicitly to ensure that we don't generate the same events redundantly
12391263
/// if users duplicatively confirm old transactions. Specifically for transactions claiming a
@@ -1567,6 +1591,7 @@ impl<Signer: EcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signer> {
15671591
(29, self.initial_counterparty_commitment_tx, option),
15681592
(31, self.funding.channel_parameters, required),
15691593
(32, self.pending_funding, optional_vec),
1594+
(33, self.htlcs_resolved_to_user, required),
15701595
});
15711596

15721597
Ok(())
@@ -1779,6 +1804,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
17791804
funding_spend_confirmed: None,
17801805
confirmed_commitment_tx_counterparty_output: None,
17811806
htlcs_resolved_on_chain: Vec::new(),
1807+
htlcs_resolved_to_user: new_hash_set(),
17821808
spendable_txids_confirmed: Vec::new(),
17831809

17841810
best_block,
@@ -4057,6 +4083,10 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
40574083
panic!("Attempted to replace shutdown script {} with {}", shutdown_script, scriptpubkey);
40584084
}
40594085
},
4086+
ChannelMonitorUpdateStep::ReleasePaymentComplete { htlc } => {
4087+
log_trace!(logger, "HTLC {htlc:?} permanently and fully resolved");
4088+
self.htlcs_resolved_to_user.insert(*htlc);
4089+
},
40604090
}
40614091
}
40624092

@@ -4087,6 +4117,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
40874117
// talking to our peer.
40884118
ChannelMonitorUpdateStep::PaymentPreimage { .. } => {},
40894119
ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {},
4120+
ChannelMonitorUpdateStep::ReleasePaymentComplete { .. } => {},
40904121
}
40914122
}
40924123

@@ -5939,6 +5970,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
59395970

59405971
let mut funding_spend_confirmed = None;
59415972
let mut htlcs_resolved_on_chain = Some(Vec::new());
5973+
let mut htlcs_resolved_to_user = Some(new_hash_set());
59425974
let mut funding_spend_seen = Some(false);
59435975
let mut counterparty_node_id = None;
59445976
let mut confirmed_commitment_tx_counterparty_output = None;
@@ -5971,6 +6003,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
59716003
(29, initial_counterparty_commitment_tx, option),
59726004
(31, channel_parameters, (option: ReadableArgs, None)),
59736005
(32, pending_funding, optional_vec),
6006+
(33, htlcs_resolved_to_user, option),
59746007
});
59756008
if let Some(payment_preimages_with_info) = payment_preimages_with_info {
59766009
if payment_preimages_with_info.len() != payment_preimages.len() {
@@ -6129,6 +6162,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
61296162
funding_spend_confirmed,
61306163
confirmed_commitment_tx_counterparty_output,
61316164
htlcs_resolved_on_chain: htlcs_resolved_on_chain.unwrap(),
6165+
htlcs_resolved_to_user: htlcs_resolved_to_user.unwrap(),
61326166
spendable_txids_confirmed: spendable_txids_confirmed.unwrap(),
61336167

61346168
best_block,

0 commit comments

Comments
 (0)