Skip to content

Conversation

@yashbhutwala
Copy link

Summary

  • Add channel_reserve_satoshis: Option<u64> field to ChannelParameters struct
  • For V1 channels: Returns Some(value) with the explicit reserve from open_channel message
  • For V2 channels: Returns None since reserve is calculated from total channel value (initiator + acceptor funding), which isn't known at OpenChannelRequest time
  • Move channel_parameters() from CommonOpenChannelFields to individual OpenChannel and OpenChannelV2 impls to handle V1/V2 difference correctly
  • Add test test_open_channel_request_channel_reserve_satoshis to verify the implementation

Fixes #3909

Revives the closed PR #3910 with the approach suggested by reviewers:

  • Uses Option<u64> instead of trying to read from wire for V2 (which doesn't have this field)
  • Follows @wpaulino's suggestion to move channel_parameters() to OpenChannel/OpenChannelV2
  • Properly documents the V1 vs V2 behavior

Test plan

  • cargo check -p lightning passes
  • All 1191 lightning tests pass (cargo test -p lightning --lib)
  • New test test_open_channel_request_channel_reserve_satoshis validates V1 channels correctly populate the field
  • All 41 channel_open_tests pass

🤖 Generated with Claude Code

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Jan 16, 2026

👋 I see @valentinewallace 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.25%. Comparing base (f9ad345) to head (e137705).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4319      +/-   ##
==========================================
+ Coverage   86.09%   86.25%   +0.16%     
==========================================
  Files         156      156              
  Lines      102804   102809       +5     
  Branches   102804   102809       +5     
==========================================
+ Hits        88508    88679     +171     
+ Misses      11788    11618     -170     
- Partials     2508     2512       +4     
Flag Coverage Δ
tests 86.25% <100.00%> (+0.16%) ⬆️

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?

@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.

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 31ebde8 to e137705 Compare January 30, 2026 16:48
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

5 participants