Skip to content

Commit 4e69514

Browse files
Support deleting legacy forward map persistence in 0.5
In 0.3+, we are taking steps to remove the requirement of regularly persisting the ChannelManager and instead rebuild the set of HTLC forwards (and the manager generally) from Channel{Monitor} data. We previously merged support for reconstructing the ChannelManager::decode_update_add_htlcs map from channel data, using a new HTLC onion field that will be present for inbound HTLCs received on 0.3+ only. The plan is that in upcoming LDK versions, the manager will reconstruct this map and the other forward/claimable/pending HTLC maps will automatically repopulate themselves on the next call to process_pending_htlc_forwards. As such, once we're in a future version that reconstructs the pending HTLC set, we can stop persisting the legacy ChannelManager maps such as forward_htlcs, pending_intercepted_htlcs since they will never be used. For 0.3 to be compatible with this future version, in this commit we detect that the manager was last written on a version of LDK that doesn't persist the legacy maps. In that case, we don't try to read the old forwards map and run the new reconstruction logic only.
1 parent c6353e4 commit 4e69514

File tree

1 file changed

+37
-17
lines changed

1 file changed

+37
-17
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16563,6 +16563,17 @@ pub fn provided_init_features(config: &UserConfig) -> InitFeatures {
1656316563
const SERIALIZATION_VERSION: u8 = 1;
1656416564
const MIN_SERIALIZATION_VERSION: u8 = 1;
1656516565

16566+
// We plan to start writing this version in 0.5.
16567+
//
16568+
// LDK 0.5+ will reconstruct the set of pending HTLCs from `Channel{Monitor}` data that started
16569+
// being written in 0.3, ignoring legacy `ChannelManager` HTLC maps on read and not writing them.
16570+
// LDK 0.5+ will automatically fail to read if the pending HTLC set cannot be reconstructed, i.e.
16571+
// if we were last written with pending HTLCs on 0.2- or if the new 0.3+ fields are missing.
16572+
//
16573+
// If 0.3 or 0.4 reads this manager version, it knows that the legacy maps were not written and
16574+
// acts accordingly.
16575+
const RECONSTRUCT_HTLCS_FROM_CHANS_VERSION: u8 = 5;
16576+
1656616577
impl_writeable_tlv_based!(PhantomRouteHints, {
1656716578
(2, channels, required_vec),
1656816579
(4, phantom_scid, required),
@@ -17322,6 +17333,8 @@ pub(super) struct ChannelManagerData<SP: SignerProvider> {
1732217333
in_flight_monitor_updates: Option<HashMap<(PublicKey, ChannelId), Vec<ChannelMonitorUpdate>>>,
1732317334
peer_storage_dir: Option<Vec<(PublicKey, Vec<u8>)>>,
1732417335
async_receive_offer_cache: AsyncReceiveOfferCache,
17336+
// The `ChannelManager` version that was written.
17337+
version: u8,
1732517338
}
1732617339

1732717340
/// Arguments for deserializing [`ChannelManagerData`].
@@ -17338,7 +17351,7 @@ impl<'a, ES: EntropySource, SP: SignerProvider, L: Logger>
1733817351
fn read<R: io::Read>(
1733917352
reader: &mut R, args: ChannelManagerDataReadArgs<'a, ES, SP, L>,
1734017353
) -> Result<Self, DecodeError> {
17341-
let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
17354+
let version = read_ver_prefix!(reader, SERIALIZATION_VERSION);
1734217355

1734317356
let chain_hash: ChainHash = Readable::read(reader)?;
1734417357
let best_block_height: u32 = Readable::read(reader)?;
@@ -17360,21 +17373,26 @@ impl<'a, ES: EntropySource, SP: SignerProvider, L: Logger>
1736017373
channels.push(channel);
1736117374
}
1736217375

17363-
let forward_htlcs_count: u64 = Readable::read(reader)?;
17364-
let mut forward_htlcs_legacy: HashMap<u64, Vec<HTLCForwardInfo>> =
17365-
hash_map_with_capacity(cmp::min(forward_htlcs_count as usize, 128));
17366-
for _ in 0..forward_htlcs_count {
17367-
let short_channel_id = Readable::read(reader)?;
17368-
let pending_forwards_count: u64 = Readable::read(reader)?;
17369-
let mut pending_forwards = Vec::with_capacity(cmp::min(
17370-
pending_forwards_count as usize,
17371-
MAX_ALLOC_SIZE / mem::size_of::<HTLCForwardInfo>(),
17372-
));
17373-
for _ in 0..pending_forwards_count {
17374-
pending_forwards.push(Readable::read(reader)?);
17375-
}
17376-
forward_htlcs_legacy.insert(short_channel_id, pending_forwards);
17377-
}
17376+
let forward_htlcs_legacy: HashMap<u64, Vec<HTLCForwardInfo>> =
17377+
if version < RECONSTRUCT_HTLCS_FROM_CHANS_VERSION {
17378+
let forward_htlcs_count: u64 = Readable::read(reader)?;
17379+
let mut fwds = hash_map_with_capacity(cmp::min(forward_htlcs_count as usize, 128));
17380+
for _ in 0..forward_htlcs_count {
17381+
let short_channel_id = Readable::read(reader)?;
17382+
let pending_forwards_count: u64 = Readable::read(reader)?;
17383+
let mut pending_forwards = Vec::with_capacity(cmp::min(
17384+
pending_forwards_count as usize,
17385+
MAX_ALLOC_SIZE / mem::size_of::<HTLCForwardInfo>(),
17386+
));
17387+
for _ in 0..pending_forwards_count {
17388+
pending_forwards.push(Readable::read(reader)?);
17389+
}
17390+
fwds.insert(short_channel_id, pending_forwards);
17391+
}
17392+
fwds
17393+
} else {
17394+
new_hash_map()
17395+
};
1737817396

1737917397
let claimable_htlcs_count: u64 = Readable::read(reader)?;
1738017398
let mut claimable_htlcs_list =
@@ -17585,6 +17603,7 @@ impl<'a, ES: EntropySource, SP: SignerProvider, L: Logger>
1758517603
in_flight_monitor_updates,
1758617604
peer_storage_dir,
1758717605
async_receive_offer_cache,
17606+
version,
1758817607
})
1758917608
}
1759017609
}
@@ -17888,6 +17907,7 @@ impl<
1788817907
mut in_flight_monitor_updates,
1788917908
peer_storage_dir,
1789017909
async_receive_offer_cache,
17910+
version: _version,
1789117911
} = data;
1789217912

1789317913
let empty_peer_state = || PeerState {
@@ -18431,7 +18451,7 @@ impl<
1843118451
// `reconstruct_manager_from_monitors` is set below. Currently it is only set in tests, randomly
1843218452
// to ensure the legacy codepaths also have test coverage.
1843318453
#[cfg(not(test))]
18434-
let reconstruct_manager_from_monitors = false;
18454+
let reconstruct_manager_from_monitors = _version >= RECONSTRUCT_HTLCS_FROM_CHANS_VERSION;
1843518455
#[cfg(test)]
1843618456
let reconstruct_manager_from_monitors =
1843718457
args.reconstruct_manager_from_monitors.unwrap_or_else(|| {

0 commit comments

Comments
 (0)