Skip to content

Commit cd4f665

Browse files
committed
Doc the on-upgrade ChannelMonitor startup persistence semantics
Because the new startup `ChannelMonitor` persistence semantics rely on new information stored in `ChannelMonitor` only for claims made in the upgraded code, users upgrading from previous version of LDK must apply the old `ChannelMonitor` persistence semantics at least once (as the old code will be used to handle partial claims).
1 parent f9d76bb commit cd4f665

File tree

8 files changed

+59
-15
lines changed

8 files changed

+59
-15
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,7 +1492,15 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
14921492

14931493
/// This is used to provide payment preimage(s) out-of-band during startup without updating the
14941494
/// off-chain state with a new commitment transaction.
1495-
pub(crate) fn provide_payment_preimage<B: Deref, F: Deref, L: Deref>(
1495+
///
1496+
/// It is used only for legacy (created prior to LDK 0.1) pending payments on upgrade, and the
1497+
/// flow that uses it assumes that this [`ChannelMonitor`] is persisted prior to the
1498+
/// [`ChannelManager`] being persisted (as the state necessary to call this method again is
1499+
/// removed from the [`ChannelManager`] and thus a persistence inversion would imply we do not
1500+
/// get the preimage back into this [`ChannelMonitor`] on startup).
1501+
///
1502+
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
1503+
pub(crate) fn provide_payment_preimage_unsafe_legacy<B: Deref, F: Deref, L: Deref>(
14961504
&self,
14971505
payment_hash: &PaymentHash,
14981506
payment_preimage: &PaymentPreimage,
@@ -5260,7 +5268,9 @@ mod tests {
52605268
preimages_slice_to_htlc_outputs!(preimages[15..20]), 281474976710654, dummy_key, &logger);
52615269
for &(ref preimage, ref hash) in preimages.iter() {
52625270
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator);
5263-
monitor.provide_payment_preimage(hash, preimage, &broadcaster, &bounded_fee_estimator, &logger);
5271+
monitor.provide_payment_preimage_unsafe_legacy(
5272+
hash, preimage, &broadcaster, &bounded_fee_estimator, &logger
5273+
);
52645274
}
52655275

52665276
// Now provide a secret, pruning preimages 10-15

lightning/src/ln/channel.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3877,12 +3877,14 @@ impl<SP: Deref> Channel<SP> where
38773877
/// Claims an HTLC while we're disconnected from a peer, dropping the [`ChannelMonitorUpdate`]
38783878
/// entirely.
38793879
///
3880+
/// This is only used for payments received prior to LDK 0.1.
3881+
///
38803882
/// The [`ChannelMonitor`] for this channel MUST be updated out-of-band with the preimage
38813883
/// provided (i.e. without calling [`crate::chain::Watch::update_channel`]).
38823884
///
38833885
/// The HTLC claim will end up in the holding cell (because the caller must ensure the peer is
38843886
/// disconnected).
3885-
pub fn claim_htlc_while_disconnected_dropping_mon_update<L: Deref>
3887+
pub fn claim_htlc_while_disconnected_dropping_mon_update_legacy<L: Deref>
38863888
(&mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage, logger: &L)
38873889
where L::Target: Logger {
38883890
// Assert that we'll add the HTLC claim to the holding cell in `get_update_fulfill_htlc`

lightning/src/ln/channelmanager.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13268,11 +13268,28 @@ where
1326813268
let peer_state = &mut *peer_state_lock;
1326913269
if let Some(ChannelPhase::Funded(channel)) = peer_state.channel_by_id.get_mut(&previous_channel_id) {
1327013270
let logger = WithChannelContext::from(&channel_manager.logger, &channel.context, Some(payment_hash));
13271-
channel.claim_htlc_while_disconnected_dropping_mon_update(claimable_htlc.prev_hop.htlc_id, payment_preimage, &&logger);
13271+
channel.claim_htlc_while_disconnected_dropping_mon_update_legacy(
13272+
claimable_htlc.prev_hop.htlc_id, payment_preimage, &&logger
13273+
);
1327213274
}
1327313275
}
1327413276
if let Some(previous_hop_monitor) = args.channel_monitors.get(&claimable_htlc.prev_hop.outpoint) {
13275-
previous_hop_monitor.provide_payment_preimage(&payment_hash, &payment_preimage, &channel_manager.tx_broadcaster, &channel_manager.fee_estimator, &channel_manager.logger);
13277+
// Note that this is unsafe as we no longer require the
13278+
// `ChannelMonitor`s to be re-persisted prior to this
13279+
// `ChannelManager` being persisted after we get started running.
13280+
// If this `ChannelManager` gets persisted first then we crash, we
13281+
// won't have the `claimable_payments` entry we need to re-enter
13282+
// this code block, causing us to not re-apply the preimage to this
13283+
// `ChannelMonitor`.
13284+
//
13285+
// We should never be here with modern payment claims, however, as
13286+
// they should always include the HTLC list. Instead, this is only
13287+
// for nodes during upgrade, and we explicitly require the old
13288+
// persistence semantics on upgrade in the release notes.
13289+
previous_hop_monitor.provide_payment_preimage_unsafe_legacy(
13290+
&payment_hash, &payment_preimage, &channel_manager.tx_broadcaster,
13291+
&channel_manager.fee_estimator, &channel_manager.logger
13292+
);
1327613293
}
1327713294
}
1327813295
let mut pending_events = channel_manager.pending_events.lock().unwrap();

lightning/src/ln/functional_tests.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3692,7 +3692,10 @@ fn test_force_close_fail_back() {
36923692
// Now check that if we add the preimage to ChannelMonitor it broadcasts our HTLC-Success..
36933693
{
36943694
get_monitor!(nodes[2], payment_event.commitment_msg.channel_id)
3695-
.provide_payment_preimage(&our_payment_hash, &our_payment_preimage, &node_cfgs[2].tx_broadcaster, &LowerBoundedFeeEstimator::new(node_cfgs[2].fee_estimator), &node_cfgs[2].logger);
3695+
.provide_payment_preimage_unsafe_legacy(
3696+
&our_payment_hash, &our_payment_preimage, &node_cfgs[2].tx_broadcaster,
3697+
&LowerBoundedFeeEstimator::new(node_cfgs[2].fee_estimator), &node_cfgs[2].logger
3698+
);
36963699
}
36973700
mine_transaction(&nodes[2], &commitment_tx);
36983701
let mut node_txn = nodes[2].tx_broadcaster.txn_broadcast();

lightning/src/ln/monitor_tests.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1883,8 +1883,10 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) {
18831883

18841884
// Cheat by giving A's ChannelMonitor the preimage to the to-be-claimed HTLC so that we have an
18851885
// HTLC-claim transaction on the to-be-revoked state.
1886-
get_monitor!(nodes[0], chan_id).provide_payment_preimage(&claimed_payment_hash, &claimed_payment_preimage,
1887-
&node_cfgs[0].tx_broadcaster, &LowerBoundedFeeEstimator::new(node_cfgs[0].fee_estimator), &nodes[0].logger);
1886+
get_monitor!(nodes[0], chan_id).provide_payment_preimage_unsafe_legacy(
1887+
&claimed_payment_hash, &claimed_payment_preimage, &node_cfgs[0].tx_broadcaster,
1888+
&LowerBoundedFeeEstimator::new(node_cfgs[0].fee_estimator), &nodes[0].logger
1889+
);
18881890

18891891
// Now get the latest commitment transaction from A and then update the fee to revoke it
18901892
let as_revoked_txn = get_local_commitment_txn!(nodes[0], chan_id);
@@ -2518,11 +2520,11 @@ fn do_test_yield_anchors_events(have_htlcs: bool) {
25182520
}
25192521

25202522
if have_htlcs {
2521-
get_monitor!(nodes[0], chan_id).provide_payment_preimage(
2523+
get_monitor!(nodes[0], chan_id).provide_payment_preimage_unsafe_legacy(
25222524
&payment_hash_2.unwrap(), &payment_preimage_2.unwrap(), &node_cfgs[0].tx_broadcaster,
25232525
&LowerBoundedFeeEstimator::new(node_cfgs[0].fee_estimator), &nodes[0].logger
25242526
);
2525-
get_monitor!(nodes[1], chan_id).provide_payment_preimage(
2527+
get_monitor!(nodes[1], chan_id).provide_payment_preimage_unsafe_legacy(
25262528
&payment_hash_1.unwrap(), &payment_preimage_1.unwrap(), &node_cfgs[1].tx_broadcaster,
25272529
&LowerBoundedFeeEstimator::new(node_cfgs[1].fee_estimator), &nodes[1].logger
25282530
);
@@ -2717,7 +2719,7 @@ fn test_anchors_aggregated_revoked_htlc_tx() {
27172719
for chan_id in [chan_a.2, chan_b.2].iter() {
27182720
let monitor = get_monitor!(nodes[1], chan_id);
27192721
for payment in [payment_a, payment_b, payment_c, payment_d].iter() {
2720-
monitor.provide_payment_preimage(
2722+
monitor.provide_payment_preimage_unsafe_legacy(
27212723
&payment.1, &payment.0, &node_cfgs[1].tx_broadcaster,
27222724
&LowerBoundedFeeEstimator::new(node_cfgs[1].fee_estimator), &nodes[1].logger
27232725
);

lightning/src/ln/reload_tests.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,8 +1041,10 @@ fn do_forwarded_payment_no_manager_persistence(use_cs_commitment: bool, claim_ht
10411041
check_added_monitors!(nodes[2], 1);
10421042

10431043
if claim_htlc {
1044-
get_monitor!(nodes[2], chan_id_2).provide_payment_preimage(&payment_hash, &payment_preimage,
1045-
&nodes[2].tx_broadcaster, &LowerBoundedFeeEstimator(nodes[2].fee_estimator), &nodes[2].logger);
1044+
get_monitor!(nodes[2], chan_id_2).provide_payment_preimage_unsafe_legacy(
1045+
&payment_hash, &payment_preimage, &nodes[2].tx_broadcaster,
1046+
&LowerBoundedFeeEstimator(nodes[2].fee_estimator), &nodes[2].logger
1047+
);
10461048
}
10471049
assert!(nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().is_empty());
10481050

lightning/src/ln/reorg_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ fn test_htlc_preimage_claim_holder_commitment_after_counterparty_commitment_reor
674674

675675
// Provide the preimage now, such that we only claim from the holder commitment (since it's
676676
// currently confirmed) and not the counterparty's.
677-
get_monitor!(nodes[1], chan_id).provide_payment_preimage(
677+
get_monitor!(nodes[1], chan_id).provide_payment_preimage_unsafe_legacy(
678678
&payment_hash, &payment_preimage, &nodes[1].tx_broadcaster,
679679
&LowerBoundedFeeEstimator(nodes[1].fee_estimator), &nodes[1].logger
680680
);
@@ -749,7 +749,7 @@ fn test_htlc_preimage_claim_prev_counterparty_commitment_after_current_counterpa
749749

750750
// Provide the preimage now, such that we only claim from the previous commitment (since it's
751751
// currently confirmed) and not the latest.
752-
get_monitor!(nodes[1], chan_id).provide_payment_preimage(
752+
get_monitor!(nodes[1], chan_id).provide_payment_preimage_unsafe_legacy(
753753
&payment_hash, &payment_preimage, &nodes[1].tx_broadcaster,
754754
&LowerBoundedFeeEstimator(nodes[1].fee_estimator), &nodes[1].logger
755755
);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Backwards Compatibility
2+
* The `ChannelManager` deserialization semantics no longer require that
3+
`ChannelMonitor`s be re-persisted after `(BlockHash, ChannelManager)::read`
4+
is called prior to normal node operation. This applies to upgraded nodes
5+
only *after* a startup with the old semantics completes at least once. IOW,
6+
you must deserialize the `ChannelManager` with upgraded LDK, persist the
7+
`ChannelMonitor`s then continue to normal startup once, and thereafter you
8+
may skip the `ChannelMonitor` persistence step.

0 commit comments

Comments
 (0)