Skip to content

Conversation

tankyleo
Copy link
Contributor

See commit messages

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Aug 28, 2025

👋 Thanks for assigning @TheBlueMatt as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@tankyleo tankyleo requested a review from TheBlueMatt August 28, 2025 08:42
@tankyleo tankyleo force-pushed the 2025-08-fallible-stats branch from 3142f12 to ff95850 Compare August 28, 2025 09:14
Copy link

codecov bot commented Aug 28, 2025

Codecov Report

❌ Patch coverage is 80.90278% with 55 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.81%. Comparing base (f3c22a7) to head (0347173).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/ln/channel.rs 77.18% 37 Missing and 10 partials ⚠️
lightning/src/sign/tx_builder.rs 89.06% 1 Missing and 6 partials ⚠️
lightning/src/ln/channelmanager.rs 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4032      +/-   ##
==========================================
- Coverage   87.84%   87.81%   -0.04%     
==========================================
  Files         176      176              
  Lines      131728   131736       +8     
  Branches   131728   131736       +8     
==========================================
- Hits       115712   115679      -33     
- Misses      13384    13412      +28     
- Partials     2632     2645      +13     
Flag Coverage Δ
fuzzing 21.50% <50.18%> (-0.12%) ⬇️
tests 87.64% <80.90%> (-0.04%) ⬇️

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.

msg.feerate_per_kw,
dust_exposure_limiting_feerate,
)
.expect("Updating the fee should never exhaust the balance after HTLCs and anchors");
Copy link
Collaborator

Choose a reason for hiding this comment

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

IMO the tx builder should fail these - if the commitment transaction cannot be built because its nonsense, it shouldn't return stats, it should fail. Also, generally, we shouldn't be expecting these calls at all IMO - if a different tx builder has different logic for deciding when something is bogus, we should let it decide that and fail rather than declaring that it must always accept.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IMO the tx builder should fail these - if the commitment transaction cannot be built because its nonsense, it shouldn't return stats, it should fail.

Not sure I understand, isn't that what's happening already ?

Also, generally, we shouldn't be expecting these calls at all IMO - if a different tx builder has different logic for deciding when something is bogus, we should let it decide that and fail rather than declaring that it must always accept.

Done, see commit below

Copy link
Contributor Author

@tankyleo tankyleo Aug 28, 2025

Choose a reason for hiding this comment

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

IMO the tx builder should fail these - if the commitment transaction cannot be built because its nonsense, it shouldn't return stats, it should fail.

Not sure I understand, isn't that what's happening already ?

Ah do you mean that it should also fail if the tx fee exhausts the balance ? Right now we fail such cases on commitment_signed; we would now fail these on receiving update_fee.

We can leave this for after 0.2 I'm thinking ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah do you mean that it should also fail if the tx fee exhausts the balance ? Right now we fail such cases on commitment_signed; we would now fail these on receiving update_fee.

Hmm, good point. Can you remind me why we validate anything at all in validate_update_fee? When we actually get a commitment_signed we'll validate what we need there (well, we should, not sure if we do), and I'm not entirely sure why we started validating it in the update_fee handler. I recall something about fee updates causing us to send counterparty commitment sigs that overflowed things, but that shouldn't matter - we won't include the new fee in counterparty commitment transactions until the peer sends their cs anyway.

We can leave this for after 0.2 I'm thinking ?

We could, but it seems like an easy change that would further reduce the code complexity in channel.rs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@TheBlueMatt Some guessing below, will be digging further:

  • Right now we validate dust exposure in validate_update_fee and "can you afford the new fee" in validate_commitment_signed
  • Previously only the build_commitment_transaction call would allow us to determine if counterparty can afford the fee.
  • We now have these commitment_stats methods, so we could totally move this "can you afford proposed fee" check from validate_commitment_signed to validate_update_fee.
  • validate_update_fee does validate dust exposure because dust exposure stats are easily provided by get_pending_htlc_stats without building a full commitment transaction.

I will attempt to clean all this up now thank you.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Right, so I think we should remove validate_update_fee entirely and just validate in validate_commitment_signed. The spec says we have to allow an update_fee that overdraws the balance as long as they claim an HTLC before they call commitment_signed, and I don't see a reason why we shouldn't just do it all there.

Copy link
Contributor Author

@tankyleo tankyleo Aug 29, 2025

Choose a reason for hiding this comment

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

@TheBlueMatt one more thing: the spec says we should check dust exposure on receiving update_fee not on receiving commitment_signed:

image

Should we move dust exposure checks to validate_commitment_signed too ?

@ldk-reviews-bot
Copy link

👋 The first review has been submitted!

Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer.

@tankyleo tankyleo self-assigned this Aug 28, 2025
@tankyleo tankyleo moved this to Goal: Merge in Weekly Goals Aug 28, 2025
@tankyleo tankyleo requested a review from TheBlueMatt August 28, 2025 18:39
Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

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

Responded to the pending comment but ultimately this is gonna need rebase on #4011

@TheBlueMatt
Copy link
Collaborator

Needs rebase now, then should be good to go 🎉

@tankyleo tankyleo force-pushed the 2025-08-fallible-stats branch from 5db254a to 0f6234c Compare September 5, 2025 20:33
@tankyleo tankyleo requested a review from TheBlueMatt September 5, 2025 20:43
@tankyleo
Copy link
Contributor Author

tankyleo commented Sep 5, 2025

@TheBlueMatt take a look at that last commit. Since we have to validate dust exposure on receiving update_fee, I move the tx fee check there as well.

@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @TheBlueMatt! 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.

@@ -4336,7 +4302,7 @@ where
dust_exposure_limiting_feerate,
self.holder_dust_limit_satoshis,
funding.get_channel_type(),
);
)?;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm, it does feel very weird that we can fail in a test context but not in a prod context. Can we either unwrap here or handle the error "gracefully"?

@@ -4553,6 +4516,18 @@ where
"Balance after HTLCs and anchors exhausted on local commitment",
))
})?;

next_local_commitment_stats
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm confused by this commit, I thought we discussed going the other way - removing validate_update_fee entirely and only validating in commitment_signed not doing any validation when we receive an update_fee? The spec mandates (IIRC) this, basically - a node is allowed to send an update_fee that overdraws its remaining funds as long as it also then claims an HTLC in an update_fulfill_htlc message before it sends a commitment_signed, so rejecting early would reject perfectly valid fee updates.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@TheBlueMatt What about dust exposure ? Seems spec says we should validate this on update_fee, not on commitment_signed ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think that's wrong? Like, we don't actually care whether the new feerate would suffice until it's actually applied to a commitment transaction, and in fact we always care about it when applied to a new commitment transaction.

The spec may be saying that with an eye towards our ability to disconnect to "reject" an update fee by not seeing the CS, but that never works in practice because peers will send their CS and can't build a new one. In practice this just means a reconnect loop instead of a channel closure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good thank you i'll delete validate_update_fee and move all checks to commitment_signed

@tankyleo tankyleo force-pushed the 2025-08-fallible-stats branch 2 times, most recently from ff85846 to 6c01026 Compare September 8, 2025 18:33
@tankyleo tankyleo requested a review from TheBlueMatt September 8, 2025 19:13
@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @TheBlueMatt! 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
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

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

Awesome! Thanks, feel free to squash.

dust_exposure_limiting_feerate,
)
.map_err(|()| {
log_info!(logger, "Attempting to fail HTLC due to balance after HTLCs and anchors exhausted on local commitment");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm, I'd rather log this trace and lean on logging further up to log globally once per HTLC at the appropriate level.

)
.map_err(|()| {
log_info!(logger, "Attempting to fail HTLC due to balance after HTLCs and anchors exhausted on local commitment");
LocalHTLCFailureReason::TemporaryChannelFailure
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm, interesting, I feel like we should add a ChannelBalanceOverdrawn on LocalHTLCFailureReason? It looks like the current code incorrectly uses DustLimit* when the peer overdraws their balance, but really this should be a different error code (which you do correctly, but we can do a specific error in LocalHTLCFailureReason now and let it encode to temp_channel_failure on the wire).

@ldk-reviews-bot
Copy link

✅ Added second reviewer: @valentinewallace

@ldk-reviews-bot
Copy link

🔔 1st Reminder

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

@carlaKC carlaKC self-requested a review September 15, 2025 14:35
@valentinewallace valentinewallace removed their request for review September 15, 2025 14:44
@tankyleo tankyleo force-pushed the 2025-08-fallible-stats branch from 6c01026 to bf5efd7 Compare September 15, 2025 22:42
@tankyleo
Copy link
Contributor Author

  • Squashed
  • Adjusted log level in can_accept_incoming_htlc
  • Introduced LocalHTLCFailureReason::ChannelBalanceOverdrawn, mapped it to UPDATE | 7

Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

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

LGTM, but sadly needs rebase now

@tankyleo tankyleo force-pushed the 2025-08-fallible-stats branch from bf5efd7 to 9f23084 Compare September 16, 2025 03:21
@tankyleo
Copy link
Contributor Author

git range-diff ecce85946584d8e5c4f3728d0d51be8f9335ec8b..bf5efd76f062272d94111a9adef2ab28594f2adc 5ae19b4fde9ff952e0ac1106990099a821372095..fdeae638e7158de05f16b1487eb3257b903787f3

1:  e171de6ec4c = 1:  5b908d77de1 Make `TxBuilder::get_next_commitment_stats` fallible
2:  b8ad2af0765 = 2:  1a82e8c921e Include HTLCs unknown by remote in `can_accept_incoming_htlc` stats
3:  d3daeabbf88 = 3:  c221d232a64 Include any pending fee updates in `can_accept_incoming_htlc` stats
4:  505eb032ff1 = 4:  1ee11d1f726 Relax feerate requirements in `TxBuilder::get_next_commitment_stats`
5:  91dae0a8927 = 5:  74fb873609a Cleanup dust exposure due to excess fees in `get_next_commitment_stats`
6:  017a33a5ae9 = 6:  d9d80b7c100 Note that we may want to apply HTLC deletes to the upcoming set of HTLCs
7:  bf5efd76f06 ! 7:  9f230840b3a Check dust exposure on receiving `commitment_signed`, not `update_fee`
    @@ lightning/src/ln/channel.rs: where
      	{
      		let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
     @@ lightning/src/ln/channel.rs: where
    - 				#[cfg(splicing)]
    + 					.unwrap_or(true);
      				let res = if has_negotiated_pending_splice && !session_received_commitment_signed {
      					funded_channel
     -						.splice_initial_commitment_signed(msg, logger)
    @@ lightning/src/ln/channel.rs: where
      						.map(|monitor_update_opt| (None, monitor_update_opt))
      				};
      
    - 				#[cfg(not(splicing))]
    --				let res = funded_channel.commitment_signed(msg, logger)
    -+				let res = funded_channel.commitment_signed(msg, fee_estimator, logger)
    - 					.map(|monitor_update_opt| (None, monitor_update_opt));
    - 
    - 				self.phase = ChannelPhase::Funded(funded_channel);
     @@ lightning/src/ln/channel.rs: where
      
      	fn validate_update_fee<F: Deref>(
    @@ lightning/src/ln/channel.rs: where
      				)
      			));
     @@ lightning/src/ln/channel.rs: where
    + 		Ok(())
      	}
      
    - 	#[rustfmt::skip]
     -	fn validate_commitment_signed<L: Deref>(
    -+	fn validate_commitment_signed<F:Deref, L: Deref>(
    ++	fn validate_commitment_signed<F: Deref, L: Deref>(
      		&self, funding: &FundingScope, transaction_number: u64, commitment_point: PublicKey,
     -		msg: &msgs::CommitmentSigned, logger: &L,
     +		msg: &msgs::CommitmentSigned, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L,
    - 	) -> Result<(HolderCommitmentTransaction, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>), ChannelError>
    + 	) -> Result<
    + 		(HolderCommitmentTransaction, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>),
    + 		ChannelError,
    + 	>
      	where
     +		F::Target: FeeEstimator,
      		L::Target: Logger,
    @@ lightning/src/ln/channel.rs: where
      		// they can actually afford the new fee now.
     -		let update_fee = if let Some((_, update_state)) = self.pending_update_fee {
     -			update_state == FeeUpdateState::RemoteAnnounced
    --		} else { false };
    +-		} else {
    +-			false
    +-		};
     -		if update_fee {
    -+		if let Some((new_feerate_per_kw, FeeUpdateState::RemoteAnnounced)) = self.pending_update_fee {
    - 			debug_assert!(!funding.is_outbound());
    --			let counterparty_reserve_we_require_msat = funding.holder_selected_channel_reserve_satoshis * 1000;
    --			if commitment_data.stats.remote_balance_before_fee_msat < commitment_data.stats.commit_tx_fee_sat * 1000 + counterparty_reserve_we_require_msat {
    --				return Err(ChannelError::close("Funding remote cannot afford proposed new fee".to_owned()));
    +-			debug_assert!(!funding.is_outbound());
    +-			let counterparty_reserve_we_require_msat =
    +-				funding.holder_selected_channel_reserve_satoshis * 1000;
    +-			if commitment_data.stats.remote_balance_before_fee_msat
    +-				< commitment_data.stats.commit_tx_fee_sat * 1000
    +-					+ counterparty_reserve_we_require_msat
    +-			{
    +-				return Err(ChannelError::close(
    +-					"Funding remote cannot afford proposed new fee".to_owned(),
    +-				));
     -			}
     -		}
     -		#[cfg(any(test, fuzzing))]
    --		{
    --			let PredictedNextFee { predicted_feerate, predicted_nondust_htlc_count, predicted_fee_sat } = *funding.next_local_fee.lock().unwrap();
    --			if predicted_feerate == commitment_data.tx.feerate_per_kw() && predicted_nondust_htlc_count == commitment_data.tx.nondust_htlcs().len() {
    ++		if let Some((new_feerate_per_kw, FeeUpdateState::RemoteAnnounced)) = self.pending_update_fee
    + 		{
    +-			let PredictedNextFee {
    +-				predicted_feerate,
    +-				predicted_nondust_htlc_count,
    +-				predicted_fee_sat,
    +-			} = *funding.next_local_fee.lock().unwrap();
    +-			if predicted_feerate == commitment_data.tx.negotiated_feerate_per_kw()
    +-				&& predicted_nondust_htlc_count == commitment_data.tx.nondust_htlcs().len()
    +-			{
     -				assert_eq!(predicted_fee_sat, commitment_data.stats.commit_tx_fee_sat);
     -			}
    ++			debug_assert!(!funding.is_outbound());
     +			self.validate_update_fee(funding, fee_estimator, new_feerate_per_kw)?;
      		}
      
    @@ lightning/src/ln/channel.rs: where
     +		#[cfg(any(test, fuzzing))]
     +		{
     +			let PredictedNextFee { predicted_feerate, predicted_nondust_htlc_count, predicted_fee_sat } = if local { *funding.next_local_fee.lock().unwrap() } else { *funding.next_remote_fee.lock().unwrap() };
    -+			if predicted_feerate == tx.feerate_per_kw() && predicted_nondust_htlc_count == tx.nondust_htlcs().len() {
    ++			if predicted_feerate == tx.negotiated_feerate_per_kw() && predicted_nondust_htlc_count == tx.nondust_htlcs().len() {
     +				assert_eq!(predicted_fee_sat, stats.commit_tx_fee_sat);
     +			}
     +		}
    @@ lightning/src/ln/channel.rs: where
      			inbound_htlc_preimages,
      			outbound_htlc_preimages,
     @@ lightning/src/ln/channel.rs: where
    + 	/// Note that our `commitment_signed` send did not include a monitor update. This is due to:
      	///   1. Updates cannot be made since the state machine is paused until `tx_signatures`.
      	///   2. We're still able to abort negotiation until `tx_signatures`.
    - 	#[cfg(splicing)]
     -	pub fn splice_initial_commitment_signed<L: Deref>(
     -		&mut self, msg: &msgs::CommitmentSigned, logger: &L,
     +	pub fn splice_initial_commitment_signed<F: Deref, L: Deref>(
    @@ lightning/src/ln/channel.rs: where
      		self.context.update_time_counter += 1;
     -
     -		core::iter::once(&self.funding)
    --			.chain(self.pending_funding.iter())
    +-			.chain(self.pending_funding().iter())
     -			.try_for_each(|funding| self.context.validate_update_fee(funding, fee_estimator, msg))
     +		Ok(())
      	}
    @@ lightning/src/ln/channel.rs: where
     -		#[cfg(any(test, fuzzing))]
     -		{
     -			let PredictedNextFee { predicted_feerate, predicted_nondust_htlc_count, predicted_fee_sat } = *funding.next_remote_fee.lock().unwrap();
    --			if predicted_feerate == counterparty_commitment_tx.feerate_per_kw() && predicted_nondust_htlc_count == counterparty_commitment_tx.nondust_htlcs().len() {
    +-			if predicted_feerate == counterparty_commitment_tx.negotiated_feerate_per_kw() && predicted_nondust_htlc_count == counterparty_commitment_tx.nondust_htlcs().len() {
     -				assert_eq!(predicted_fee_sat, commitment_data.stats.commit_tx_fee_sat);
     -			}
     -		}
-:  ----------- > 8:  fdeae638e71 Fix broken intra doc links, these were causing beta CI to fail

@tankyleo
Copy link
Contributor Author

Rebasing one more time :)

Anytime we ask `TxBuilder` for stats on a commitment transaction,
`TxBuilder` can now return an error to indicate that a balance not
including the commitment transaction fee has been overdrawn. We then
map this error to the appropriate action depending on where in the
life cycle of the channel the error occurred.

We now do not require that `channel_value_satoshis * 1000` is greater
than or equal to `value_to_holder_msat`; we previously would panic
in this case.
While these HTLCs may currently be unknown to our counterparty, they can
end up in commitments soon. Moreover, we are considering failing a
single HTLC here, not the entire channel, so we opt to be conservative
in what we accept to forward.
While these fee updates may currently be unknown to our counterparty,
they can end up in commitments soon. Moreover, we are considering
failing a single HTLC here, not the entire channel, so we opt to be
conservative in what we accept to forward.
We sometimes do not have easy access to the
`dust_exposure_limiting_feerate`, yet we are still interested in basic
stats on commitments like balances and transaction fees. So we relax
the requirement that the `dust_exposure_limiting_feerate` is always set
when `feerate_per_kw` is not 0.
We allow a peer to send an `update_fee` message that pushes the dust
exposure over our max as long as they send HTLC updates that bring the
dust exposure back down under the limit before they send
`commitment_signed`.
@tankyleo tankyleo force-pushed the 2025-08-fallible-stats branch from fdeae63 to 0347173 Compare September 16, 2025 21:58
@tankyleo
Copy link
Contributor Author

git range-diff main fdeae63 0347173

1:  5b908d77de1 = 1:  bf6d09808fe Make `TxBuilder::get_next_commitment_stats` fallible
2:  1a82e8c921e = 2:  1f90b09ef41 Include HTLCs unknown by remote in `can_accept_incoming_htlc` stats
3:  c221d232a64 = 3:  e5bd768ec90 Include any pending fee updates in `can_accept_incoming_htlc` stats
4:  1ee11d1f726 = 4:  593bb0666df Relax feerate requirements in `TxBuilder::get_next_commitment_stats`
5:  74fb873609a = 5:  e64287fd1c2 Cleanup dust exposure due to excess fees in `get_next_commitment_stats`
6:  d9d80b7c100 = 6:  65e9287dd25 Note that we may want to apply HTLC deletes to the upcoming set of HTLCs
7:  9f230840b3a ! 7:  03471733a98 Check dust exposure on receiving `commitment_signed`, not `update_fee`
    @@ lightning/src/ln/channel.rs: where
        /// Note that our `commitment_signed` send did not include a monitor update. This is due to:
        ///   1. Updates cannot be made since the state machine is paused until `tx_signatures`.
        ///   2. We're still able to abort negotiation until `tx_signatures`.
    --  pub fn splice_initial_commitment_signed<L: Deref>(
    +-  fn splice_initial_commitment_signed<L: Deref>(
     -          &mut self, msg: &msgs::CommitmentSigned, logger: &L,
    -+  pub fn splice_initial_commitment_signed<F: Deref, L: Deref>(
    ++  fn splice_initial_commitment_signed<F: Deref, L: Deref>(
     +          &mut self, msg: &msgs::CommitmentSigned, fee_estimator: &LowerBoundedFeeEstimator<F>,
     +          logger: &L,
        ) -> Result<Option<ChannelMonitorUpdate>, ChannelError>
    @@ lightning/src/ln/channel.rs: where
     +          F::Target: FeeEstimator,
                L::Target: Logger,
        {
    -           if !self.context.channel_state.is_interactive_signing()
    +           debug_assert!(self
     @@ lightning/src/ln/channel.rs: where
                        transaction_number,
                        commitment_point,
8:  fdeae638e71 < -:  ----------- Fix broken intra doc links, these were causing beta CI to fail

@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @TheBlueMatt @carlaKC! 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 @TheBlueMatt @carlaKC! 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
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

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

LGTM, one additional suggestion but it should probably wait for a followup so that we can land this for 0.2.

pub(crate) fn get_holder_counterparty_balances_incl_fee_msat(
&self,
) -> (Option<u64>, Option<u64>) {
pub(crate) fn get_holder_counterparty_balances_incl_fee_msat(&self) -> Result<(u64, u64), ()> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

It would be nice to leave this infallible by failing in the case someone overdrew their funds considering fees directly in get_next_commitment_stats. Since we intend this to eventually be public, that probably means we have to change the fields to *_balance_after_fee_msat so that the struct can't represent an invalid state.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

100% it's the goal, the blocker to switching those fields to _after_fee_msat has been can_accept_incoming_htlc but should be doable

// this should be set to the dust exposure that would result from us adding an additional nondust outbound
// htlc on the counterparty's commitment transaction.
pub extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat: Option<u64>,
pub extra_accepted_htlc_dust_exposure_msat: u64,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we intend to start using this soon?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The plan is to use it in whatever we come up with for get_available_balances

@TheBlueMatt
Copy link
Collaborator

You're up @carlaKC

@TheBlueMatt TheBlueMatt added this to the 0.2 milestone Sep 18, 2025
@TheBlueMatt
Copy link
Collaborator

Optimistically tagging 0.2, since this removes quite a few asserts and unwraps that are probably right, but really would be nice to ship without.

Copy link
Contributor

@carlaKC carlaKC left a comment

Choose a reason for hiding this comment

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

Great follow up, LGTM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Goal: Merge
Development

Successfully merging this pull request may close these issues.

4 participants