Skip to content

Commit b389984

Browse files
authored
Merge pull request #4599 from valentinewallace/2026-05-no-persist-onions-yet
Don't persist inbound committed onions in prod
2 parents 2af4096 + b82b6a4 commit b389984

3 files changed

Lines changed: 23 additions & 22 deletions

File tree

lightning-tests/src/upgrade_downgrade_tests.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -540,11 +540,10 @@ fn upgrade_mid_htlc_intercept_forward() {
540540
}
541541

542542
fn do_upgrade_mid_htlc_forward(test: MidHtlcForwardCase) {
543-
// In 0.3, we started reconstructing the `ChannelManager`'s HTLC forwards maps from the HTLCs
544-
// contained in `Channel`s, as part of removing the requirement to regularly persist the
545-
// `ChannelManager`. However, HTLC forwards can only be reconstructed this way if they were
546-
// received on 0.3 or higher. Test that HTLC forwards that were serialized on <=0.2 will still
547-
// succeed when read on 0.3+.
543+
// In an upcoming version, we plan to start reconstructing the `ChannelManager`'s HTLC forwards
544+
// maps from the HTLCs contained in `Channel`s, as part of removing the requirement to regularly
545+
// persist the `ChannelManager`. Preemptively test that HTLC forwards that were serialized on
546+
// <=0.2 will still succeed when read on this upcoming version.
548547
let (node_a_ser, node_b_ser, node_c_ser, mon_a_1_ser, mon_b_1_ser, mon_b_2_ser, mon_c_1_ser);
549548
let (node_a_id, node_b_id, node_c_id);
550549
let (payment_secret_bytes, payment_hash_bytes, payment_preimage_bytes);

lightning/src/ln/channel.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,7 @@ enum InboundUpdateAdd {
369369
blinded_failure: Option<BlindedFailure>,
370370
outbound_hop: OutboundHop,
371371
},
372-
/// This HTLC was received pre-LDK 0.3, before we started persisting the onion for inbound
373-
/// committed HTLCs.
372+
/// This HTLC was received before we started persisting the onion for inbound committed HTLCs.
374373
Legacy,
375374
}
376375

@@ -8051,8 +8050,9 @@ where
80518050
Ok(())
80528051
}
80538052

8054-
/// Returns true if any committed inbound HTLCs were received pre-LDK 0.3 and cannot be used
8055-
/// during `ChannelManager` deserialization to reconstruct the set of pending HTLCs.
8053+
/// Returns true if any committed inbound HTLCs were received before we started serializing
8054+
/// inbound committed payment onions in `Channel` and cannot be used during `ChannelManager`
8055+
/// deserialization to reconstruct the set of pending HTLCs.
80568056
pub(super) fn has_legacy_inbound_htlcs(&self) -> bool {
80578057
self.context.pending_inbound_htlcs.iter().any(|htlc| {
80588058
matches!(
@@ -15873,6 +15873,7 @@ impl<SP: SignerProvider> Writeable for FundedChannel<SP> {
1587315873
}
1587415874
}
1587515875
let mut removed_htlc_attribution_data: Vec<&Option<AttributionData>> = Vec::new();
15876+
#[cfg_attr(not(test), allow(unused_mut))]
1587615877
let mut inbound_committed_update_adds: Vec<&InboundUpdateAdd> = Vec::new();
1587715878
(self.context.pending_inbound_htlcs.len() as u64 - dropped_inbound_htlcs).write(writer)?;
1587815879
for htlc in self.context.pending_inbound_htlcs.iter() {
@@ -15893,9 +15894,10 @@ impl<SP: SignerProvider> Writeable for FundedChannel<SP> {
1589315894
2u8.write(writer)?;
1589415895
htlc_resolution.write(writer)?;
1589515896
},
15896-
&InboundHTLCState::Committed { ref update_add_htlc } => {
15897+
&InboundHTLCState::Committed { update_add_htlc: ref _update_add } => {
1589715898
3u8.write(writer)?;
15898-
inbound_committed_update_adds.push(update_add_htlc);
15899+
#[cfg(test)]
15900+
inbound_committed_update_adds.push(_update_add);
1589915901
},
1590015902
&InboundHTLCState::LocalRemoved(ref removal_reason) => {
1590115903
4u8.write(writer)?;

lightning/src/ln/channelmanager.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17713,16 +17713,16 @@ pub fn provided_init_features(config: &UserConfig) -> InitFeatures {
1771317713
const SERIALIZATION_VERSION: u8 = 1;
1771417714
const MIN_SERIALIZATION_VERSION: u8 = 1;
1771517715

17716-
// We plan to start writing this version in 0.5.
17716+
// We plan to start writing this version a few versions after we start writing inbound committed
17717+
// payment onions in `Channel`, which is already done in tests but not yet switched on in prod.
1771717718
//
17718-
// LDK 0.5+ will reconstruct the set of pending HTLCs from `Channel{Monitor}` data that started
17719-
// being written in 0.3, ignoring legacy `ChannelManager` HTLC maps on read and not writing them.
17720-
// LDK 0.5+ will automatically fail to read if the pending HTLC set cannot be reconstructed, i.e.
17721-
// if we were last written with pending HTLCs on 0.2- or if the new 0.3+ fields are missing.
17719+
// If we see this version on read, we will use said onions when reconstructing the set of pending
17720+
// HTLCs, ignoring legacy `ChannelManager` HTLC maps on read and not writing them. We'll also
17721+
// automatically fail to read if the pending HTLC set cannot be reconstructed, i.e. if the new
17722+
// payment onion field is missing.
1772217723
//
17723-
// If 0.3 or 0.4 reads this manager version, it knows that the legacy maps were not written and
17724-
// acts accordingly.
17725-
const RECONSTRUCT_HTLCS_FROM_CHANS_VERSION: u8 = 2;
17724+
// Left as `None` for now until we are committed to writing inbound committed onions in `Channel`s.
17725+
const RECONSTRUCT_HTLCS_FROM_CHANS_VERSION: Option<u8> = None;
1772617726

1772717727
impl_writeable_tlv_based!(PhantomRouteHints, {
1772817728
(2, channels, required_vec),
@@ -18549,7 +18549,7 @@ impl<'a, ES: EntropySource, SP: SignerProvider, L: Logger>
1854918549
}
1855018550

1855118551
let forward_htlcs_legacy: HashMap<u64, Vec<HTLCForwardInfo>> =
18552-
if version < RECONSTRUCT_HTLCS_FROM_CHANS_VERSION {
18552+
if RECONSTRUCT_HTLCS_FROM_CHANS_VERSION.map_or(true, |v| version < v) {
1855318553
let forward_htlcs_count: u64 = Readable::read(reader)?;
1855418554
let mut fwds = hash_map_with_capacity(cmp::min(forward_htlcs_count as usize, 128));
1855518555
for _ in 0..forward_htlcs_count {
@@ -19695,7 +19695,8 @@ impl<
1969519695
// `reconstruct_manager_from_monitors` is set below. Currently we set in tests randomly to
1969619696
// ensure the legacy codepaths also have test coverage.
1969719697
#[cfg(not(test))]
19698-
let reconstruct_manager_from_monitors = _version >= RECONSTRUCT_HTLCS_FROM_CHANS_VERSION;
19698+
let reconstruct_manager_from_monitors =
19699+
RECONSTRUCT_HTLCS_FROM_CHANS_VERSION.is_some_and(|v| _version >= v);
1969919700
#[cfg(test)]
1970019701
let reconstruct_manager_from_monitors =
1970119702
args.reconstruct_manager_from_monitors.unwrap_or_else(|| {
@@ -19758,7 +19759,6 @@ impl<
1975819759
if reconstruct_manager_from_monitors {
1975919760
if let Some(chan) = peer_state.channel_by_id.get(channel_id) {
1976019761
if let Some(funded_chan) = chan.as_funded() {
19761-
// Legacy HTLCs are from pre-LDK 0.3 and cannot be reconstructed.
1976219762
if funded_chan.has_legacy_inbound_htlcs() {
1976319763
return Err(DecodeError::InvalidValue);
1976419764
}

0 commit comments

Comments
 (0)