Skip to content

Expose channel_reserve_satoshis via InboundChannelFunds::PushMsat#4319

Open
yashbhutwala wants to merge 2 commits intolightningdevkit:mainfrom
yashbhutwala:expose-channel-reserve-satoshis
Open

Expose channel_reserve_satoshis via InboundChannelFunds::PushMsat#4319
yashbhutwala wants to merge 2 commits intolightningdevkit:mainfrom
yashbhutwala:expose-channel-reserve-satoshis

Conversation

@yashbhutwala
Copy link

@yashbhutwala yashbhutwala commented Jan 16, 2026

Summary

Expose the channel_reserve_satoshis value from V1 open_channel messages to users handling Event::OpenChannelRequest.

  • Convert InboundChannelFunds::PushMsat from a tuple variant to a struct variant carrying both push_msat and channel_reserve_satoshis
  • For V2 (dual-funded) channels, the reserve is not included since it depends on the acceptor's funding contribution, which isn't known at event time
  • Restore CommonOpenChannelFields::channel_parameters() (keeping ChannelParameters free of V1-specific fields)
  • Add tests for both V1 and V2 channel open request events

Fixes #3909

Revives the closed PR #3910 with the approach agreed upon by reviewers (@tnull, @TheBlueMatt): fold the reserve into InboundChannelFunds rather than adding an Option<u64> to ChannelParameters.

Test plan

  • cargo check -p lightning passes
  • All 1210 lightning lib tests pass (cargo +1.75.0 test -p lightning --lib)
  • New test test_open_channel_request_channel_reserve_satoshis validates V1 channels correctly populate the field
  • New test test_open_channel_request_channel_reserve_satoshis_v2 validates V2 channels use DualFunded variant
  • All 42 channel_open_tests pass

🤖 Generated with Claude Code

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Jan 16, 2026

👋 I see @tnull was un-assigned.
If you'd like another reviewer assignment, please click here.

@codecov
Copy link

codecov bot commented Jan 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.20%. Comparing base (caf0aac) to head (aa3dd72).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4319      +/-   ##
==========================================
+ Coverage   86.05%   86.20%   +0.15%     
==========================================
  Files         156      156              
  Lines      103384   103392       +8     
  Branches   103384   103392       +8     
==========================================
+ Hits        88964    89130     +166     
+ Misses      11905    11745     -160     
- Partials     2515     2517       +2     
Flag Coverage Δ
tests 86.20% <100.00%> (+0.15%) ⬆️

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.

@tankyleo tankyleo self-requested a review January 16, 2026 18:14
@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @valentinewallace @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

1 similar comment
@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @valentinewallace @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 2nd Reminder

Hey @valentinewallace @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

1 similar comment
@ldk-reviews-bot
Copy link

🔔 2nd Reminder

Hey @valentinewallace @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@yashbhutwala
Copy link
Author

@tnull @dunxen @TheBlueMatt please review 🙏

@ldk-reviews-bot
Copy link

🔔 3rd Reminder

Hey @valentinewallace @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

1 similar comment
@ldk-reviews-bot
Copy link

🔔 3rd Reminder

Hey @valentinewallace @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 4th Reminder

Hey @valentinewallace @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

1 similar comment
@ldk-reviews-bot
Copy link

🔔 4th Reminder

Hey @valentinewallace @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Copy link
Contributor

@valentinewallace valentinewallace left a comment

Choose a reason for hiding this comment

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

Basically looks good. Probably good if @tankyleo takes a look since he's working on channel reserve stuff

@yashbhutwala yashbhutwala force-pushed the expose-channel-reserve-satoshis branch 2 times, most recently from e8cabf3 to 48a70a8 Compare January 27, 2026 19:00
Copy link
Contributor

@tankyleo tankyleo left a comment

Choose a reason for hiding this comment

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

Thanks for the PR excuse the delay on my side ! I'll ping tnull as well since he is a consumer of this API and opened the issue in the first place

pub(super) fn channel_parameters(&self) -> msgs::ChannelParameters {
let (common_fields, channel_reserve_satoshis) = match self {
Self::V1(msg) => (&msg.common_fields, Some(msg.channel_reserve_satoshis)),
Self::V2(msg) => (&msg.common_fields, None),
Copy link
Contributor

Choose a reason for hiding this comment

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

The test suite still passes if I set this to Some(0), let's add coverage for the V2 case.

Copy link
Author

Choose a reason for hiding this comment

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

Done! Added test_open_channel_request_channel_reserve_satoshis_v2 which verifies that channel_reserve_satoshis is None for V2 (dual-funded) channels. This ensures the V2 code path is properly covered.

// For V1 channels, channel_reserve_satoshis should be Some with the value from the message
assert_eq!(
params.channel_reserve_satoshis,
Some(expected_reserve),
Copy link
Contributor

Choose a reason for hiding this comment

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

As described elsewhere, let's also add coverage for the V2 case

Copy link
Author

Choose a reason for hiding this comment

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

Done! The new V2 test is added alongside the V1 test.

Comment on lines 266 to 269
/// The minimum value unencumbered by HTLCs for the counterparty to keep in the channel.
///
/// For V1 channels (`open_channel`), this is the explicit `channel_reserve_satoshis` value
/// from the counterparty.
Copy link
Contributor

Choose a reason for hiding this comment

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

As described above, this is a subset of CommonOpenChannelFields, and the channel_reserve_satoshis of the OpenChannel message actually sets the minimum value that the non-channel-initiator must keep in the channel, and not the counterparty (as long as we define the counterparty here to be the sender of the OpenChannel message).

Copy link
Author

Choose a reason for hiding this comment

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

Good catch! Fixed the documentation to clarify that:

  • The reserve is for the "non-channel-initiator" to keep (not "counterparty")
  • The value comes "from the channel initiator" (not "from the counterparty")

This makes it clear that from the OpenChannelRequest perspective (where we're the non-initiator receiving the message), the initiator is specifying what reserve we must maintain.

/// the final reserve value cannot be determined at that point.
///
/// [`Event::OpenChannelRequest`]: crate::events::Event::OpenChannelRequest
pub channel_reserve_satoshis: Option<u64>,
Copy link
Contributor

@tankyleo tankyleo Jan 27, 2026

Choose a reason for hiding this comment

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

A question for @tnull : OpenChannelV2 drops both the channel_reserve_satoshis, and push_msat fields. For the push_msats field, we currently handle this transition in the OpenChannelRequest event with an InboundChannelFunds enum, with PushMsat(u64) as the V1 variant, and DualFunded as the V2 variant.

We also note for InboundChannelFunds that it "allows the differentiation between a request for a dual-funded and non-dual-funded channel."

Seems to me now we can also differentiate V1 vs V2 based on the channel_reserve_satohis field.

To keep things consistent, would it be worth moving push_msats to ChannelParameters too, and set it to None in the V2 case, like we are doing here for channel_reserve_satoshis ?

Copy link
Author

Choose a reason for hiding this comment

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

This is a good point about consistency. I'll leave this design question for @tnull to weigh in on, as it would be a larger change to consolidate push_msats into ChannelParameters as well.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I kinda feel like we should include a value here for v2 that is the "reserve if you don't contribute" value and call it like likely_channel_reserve_satoshis? Otherwise it just feels weird that we have a value here that we expect to eventually be useless?

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for the suggestion @TheBlueMatt! To clarify - would you prefer:

  1. Rename to likely_channel_reserve_satoshis and populate it for V2 with max(1% of initiator_funding, dust_limit), or
  2. Keep a separate field/approach?

Also, does this address @tankyleo's earlier question about push_msats consistency, or should we still consider consolidating that into ChannelParameters as well?

Copy link
Contributor

Choose a reason for hiding this comment

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

A question for @tnull : OpenChannelV2 drops both the channel_reserve_satoshis, and push_msat fields. For the push_msats field, we currently handle this transition in the OpenChannelRequest event with an InboundChannelFunds enum, with PushMsat(u64) as the V1 variant, and DualFunded as the V2 variant.

Yeah, IMO makes sense to keep it consistent (and eventually drop both once we can deprecate v1^^).

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yea dont see why it should be a separate field?

Copy link
Author

Choose a reason for hiding this comment

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

Agreed — moved channel_reserve_satoshis out of ChannelParameters and into InboundChannelFunds::PushMsat as a struct variant:

pub enum InboundChannelFunds {
    PushMsat {
        push_msat: u64,
        channel_reserve_satoshis: u64,
    },
    DualFunded,
}

This keeps ChannelParameters free of V1-specific fields, and the V1/V2 distinction is handled entirely by the enum — consistent with how push_msat already differentiates. Also restored CommonOpenChannelFields::channel_parameters() and removed the OpenChannelMessageRef::channel_parameters() helper.

@TheBlueMatt @tnull would appreciate a re-review when you get a chance!

Copy link
Contributor

Choose a reason for hiding this comment

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

Conceptually makes sense to me to have such an enum (without having had a closer look at the code), but it is a bit odd to have channel_reserve_satoshis under 'inbound channel funds' as the reserve is ofc not an 'inbound fund'. Not sure what a better naming scheme would be here though.

@tankyleo tankyleo requested a review from tnull January 27, 2026 21:07
@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @tnull @valentinewallace! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@valentinewallace valentinewallace removed their request for review January 29, 2026 19:53
@yashbhutwala yashbhutwala force-pushed the expose-channel-reserve-satoshis branch from 9423f93 to 31ebde8 Compare January 29, 2026 20:39
@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @tnull! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@yashbhutwala yashbhutwala force-pushed the expose-channel-reserve-satoshis branch from 31ebde8 to e137705 Compare January 30, 2026 16:48
@ldk-reviews-bot
Copy link

🔔 2nd Reminder

Hey @tnull! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@tnull tnull removed their request for review February 2, 2026 13:13
Add `channel_reserve_satoshis` field to `ChannelParameters` struct to expose
the channel reserve value in `OpenChannelRequest` events. This allows users
handling inbound channel requests to see the reserve requirement.

For V1 channels, this is the explicit value from the `open_channel` message.
For V2 (dual-funded) channels, this is `None` since the reserve is calculated
based on total channel value which isn't known until both parties contribute.

Also implements `channel_parameters()` on `OpenChannelMessageRef` to DRY up
the code, as suggested in review.
@yashbhutwala yashbhutwala force-pushed the expose-channel-reserve-satoshis branch from e137705 to 1ba60a2 Compare February 10, 2026 20:19
…dChannelFunds`

Per reviewer feedback, `channel_reserve_satoshis` is better placed in
the `InboundChannelFunds` enum rather than as a separate `Option<u64>`
on `ChannelParameters`. This is consistent with how V1 vs V2 channel
differences are already handled via the enum.

- Convert `InboundChannelFunds::PushMsat` from a tuple variant to a
  struct variant with `push_msat` and `channel_reserve_satoshis` fields
- Remove `channel_reserve_satoshis` field from `ChannelParameters`
- Restore `CommonOpenChannelFields::channel_parameters()` method
- Remove `OpenChannelMessageRef::channel_parameters()` helper
- Update tests to check reserve from the enum variant

Co-Authored-By: Claude (claude.ai)
@yashbhutwala yashbhutwala changed the title Expose channel_reserve_satoshis via ChannelParameters Expose channel_reserve_satoshis via InboundChannelFunds::PushMsat Feb 10, 2026
@tnull tnull removed their request for review February 12, 2026 12:43
@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @TheBlueMatt @valentinewallace @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

2 similar comments
@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @TheBlueMatt @valentinewallace @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @TheBlueMatt @valentinewallace @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose channel_reserve_satoshis via ChannelParameters in OpenChannelRequest

6 participants