Skip to content

Reload channelmanager with channel data from monitors - #4151

Closed
joostjager wants to merge 5 commits into
lightningdevkit:mainfrom
joostjager:chanmgr-refactor-passthrough
Closed

Reload channelmanager with channel data from monitors#4151
joostjager wants to merge 5 commits into
lightningdevkit:mainfrom
joostjager:chanmgr-refactor-passthrough

Conversation

@joostjager

@joostjagerjoostjager commented Oct 9, 2025

Copy link
Copy Markdown
Contributor

PoC branch to try out persisting channels with the monitors rather than chanmgr. Goal: fix force closures.

Builds on #4218

@ldk-reviews-bot

Copy link
Copy Markdown

👋 Hi! I see this is a draft PR.
I'll wait to assign reviewers until you mark it as ready for review.
Just convert it out of draft status when you're ready for review!

@joostjagerjoostjager self-assigned this Oct 9, 2025
@joostjager
joostjagerforce-pushed the chanmgr-refactor-passthrough branch 2 times, most recently from dd9d6db to c9d03d4CompareOctober 30, 2025 15:06
@joostjager
joostjagerforce-pushed the chanmgr-refactor-passthrough branch 3 times, most recently from 2eb7981 to 4eb87c1CompareNovember 18, 2025 14:24
Comment threadlightning/src/ln/channelmanager.rs Outdated
let mut failed_htlcs = Vec::new();
let channel_count: u64 = Readable::read(reader)?;

// Discard channel manager versions of channels.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we'll need to use these manager versions of channels if the monitor versions aren't set (i.e. reading a manager that was last serialized on <= 0.2). Ideal would be to have an upgrade test, i.e. in upgrade_downgrade_tests.rs.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to leave this until we've got solid confidence in the approach taken? Ofc agreed that we need to implement upgrade.


/// The encoded channel data associated with this ChannelMonitor, if any.
#[cfg(feature = "safe_channels")]
pub encoded_channel: Option<Vec<u8>>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you explore encoding the FundedChannel itself rather than a bag of bytes? I guess it would require propagating the signer trait parameter, which is kind of annoying?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered it, but indeed, the signer parameter is annoying. But your comment did make me think again. I will try and see what we can do with a copy of FundedChannel just for data storage. Perhaps that's useful too once we start stripping out the redundant fields?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I noticed while trying this is that ChannelContext contains blocked_monitor_updates: Vec<PendingChannelMonitorUpdate>. PendingChannelMonitorUpdate will contain FundedChannel snapshots. Nesting 😨

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// for the safe_channels feature.
#[cfg(feature = "safe_channels")]
if let Some(ref encoded_channel) = channel_monitor.encoded_channel {
channel_monitor.check_encoded_channel_consistency(encoded_channel);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be better to have the above docs (or duplicate them) on the method itself

Comment on lines +1432 to +1433
/// The serialized channel state as provided via the last `ChannelMonitorUpdate` or via a call to
/// [`ChannelMonitor::update_encoded_channel`].

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe note that this is a FundedChannel and explain why we're encoding it here?

if let Ok(check_data) = check_res {
debug_assert!(
check_data.cur_holder_commitment_transaction_number
<= self.get_cur_holder_commitment_number(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you document generally why it's okay for the channel to be behind the monitor (but not ahead)?

Comment threadlightning/src/ln/channel.rs Outdated
}

#[cfg(feature = "safe_channels")]
pub fn read_check_data<R: io::Read>(reader: &mut R) -> Result<ChannelStateCheckData, DecodeError> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs on this method?

@joostjager
joostjagerforce-pushed the chanmgr-refactor-passthrough branch from 4eb87c1 to 1adfd7dCompareNovember 19, 2025 09:39
@codecov

codecovBot commented Nov 19, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 58.55856% with 46 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.29%. Comparing base (de384ff) to head (501c599).
⚠️ Report is 571 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channel.rs45.88%46 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4151 +/- ##
==========================================
- Coverage 89.33% 89.29% -0.05% 
==========================================
Files 180 180 Lines 139042 139132 +90 Branches 139042 139132 +90 ==========================================
+ Hits 124219 124231 +12 - Misses 12196 12275 +79 + Partials 2627 2626 -1 
FlagCoverage Δ
fuzzing35.95% <26.47%> (-0.02%)⬇️
tests88.65% <58.55%> (-0.05%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@joostjager

Copy link
Copy Markdown
ContributorAuthor

Added more cfg gating for safe_channels to make CI pass. Did allow unused warnings for the skipped tests, because otherwise an extreme amount of uses gating would be needed.

@joostjagerjoostjager changed the title Store channel alongside channel monitorReload channelmanager with channel data from monitorsNov 19, 2025
@joostjager
joostjagerforce-pushed the chanmgr-refactor-passthrough branch 2 times, most recently from 5967f55 to b096bf7CompareNovember 19, 2025 16:08
@joostjager

Copy link
Copy Markdown
ContributorAuthor

If we go with unencoded channels in the monitors and monitor updates, this PR would come out along the following lines: https://github.com/lightningdevkit/rust-lightning/compare/main...joostjager:rust-lightning:chanmgr-refactor-passthrough-unencoded?expand=1

In that branch, I've also stripped away all of chanmgr::read except for the static data. This leads to 85 failing tests, which would be the base line to go work off of.

@joostjager
joostjagerforce-pushed the chanmgr-refactor-passthrough branch from e87a727 to 5859132CompareNovember 27, 2025 09:46
@joostjager

Copy link
Copy Markdown
ContributorAuthor

Rebased PR on top of unencoded channel state in ChannelMonitorUpdates. Also switched to clean-slate tlv serialization for chan mgr with only the static fields. Total number of tests failing without any reconstruction attempts is 44. Seems not the worst starting point.

@joostjager
joostjagerforce-pushed the chanmgr-refactor-passthrough branch 2 times, most recently from 9168f08 to 74285c1CompareNovember 27, 2025 12:15
Additional trace logs to help with debugging.
Add a new `safe_channels` feature flag that gates in-development work
toward persisting channel monitors and channels atomically, preventing
them from desynchronizing and causing force closures.
This commit begins that transition by storing both pieces together and
adding consistency checks during writes. These checks mirror what the
channel manager currently validates only on reload, but performing them
earlier increases coverage and surfaces inconsistencies sooner.
@joostjager

Copy link
Copy Markdown
ContributorAuthor

Implemented safe channels via #4351

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants

@joostjager@ldk-reviews-bot@valentinewallace