-
Notifications
You must be signed in to change notification settings - Fork 416
Validate negative funding contributions in splice_init
and splice_ack
messages
#4011
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
tankyleo
commented
Aug 14, 2025
👋 I see @valentinewallace was un-assigned. |
splice_ack
and splice_init
messagessplice_init
and splice_ack
messages
6d6b07c
to
93965c6
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4011 +/- ##
==========================================
- Coverage 88.78% 88.76% -0.03%
==========================================
Files 176 176
Lines 128139 128533 +394
Branches 128139 128533 +394
==========================================
+ Hits 113768 114087 +319
- Misses 11803 11859 +56
- Partials 2568 2587 +19
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
🔔 1st Reminder Hey @wpaulino! This PR has been waiting for your review. |
🔔 2nd Reminder Hey @wpaulino! This PR has been waiting for your review. |
On hold until splice-out PR gets in. |
🔔 3rd Reminder Hey @wpaulino! This PR has been waiting for your review. |
As much as possible, we want to only mutate state once we are done with input validation. This also removes complaints when helper functions during validation take a `&self`.
As in `splice_init`, this helps clearly delineate `splice_ack` message validation from the subsequent state mutations. This is a code-move.
We will validate the reserve requirements on the new `FundingScope` in `validate_splice_contribution`.
`NextCommitmentStats` provides the commitment transaction fee as a separate value to assist with applying a multiplier on it in `can_accept_incoming_htlc`. Nonetheless in most cases, we want the balances to include the commitment transaction fee, so here we add a helper that gives us these balances.
This applies to both `splice_init` and `splice_ack` messages. From BOLT 2: ``` - If `funding_contribution_satoshis` is negative and its absolute value is greater than the sending node's current channel balance: - MUST send a `warning` and close the connection or send an `error` and fail the channel. ``` We allow the remote to be below the new reserve as long as their funding contribution is not negative; we don't care whether they were above or below the previous funding reserve.
93965c6
to
d0023e3
Compare
@@ -11095,7 +11095,7 @@ where | |||
}) | |||
} | |||
|
|||
/// Handle splice_ack | |||
/// See also [`validate_splice_ack`] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: just remove the comment
impl NextCommitmentStats { | ||
pub(crate) fn get_balances_including_fee_msat(&self) -> (Option<u64>, Option<u64>) { | ||
let holder_balance_incl_fee_msat = if self.is_outbound_from_holder { | ||
self.holder_balance_before_fee_msat |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this already have the anchor outputs value subtracted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
let counterparty_balance_incl_fee_msat = if self.is_outbound_from_holder { | ||
self.counterparty_balance_before_fee_msat | ||
} else { | ||
self.counterparty_balance_before_fee_msat | ||
.and_then(|balance| balance.checked_sub(self.commit_tx_fee_sat * 1000)) | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let counterparty_balance_incl_fee_msat = if self.is_outbound_from_holder { | |
self.counterparty_balance_before_fee_msat | |
} else { | |
self.counterparty_balance_before_fee_msat | |
.and_then(|balance| balance.checked_sub(self.commit_tx_fee_sat * 1000)) | |
}; | |
let counterparty_balance_incl_fee_msat = | |
self.counterparty_balance_before_fee_msat.and_then(|balance| { | |
if self.is_outbound_from_holder { | |
balance | |
} else { | |
balance.checked_sub(self.commit_tx_fee_sat * 1000) | |
} | |
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The two branches of the if statement here don't return the same type - will take another look later
// This *should* have no effect because no HTLC updates should be pending, but even if it does, | ||
// the result may be a failed negotiation (and not a force-close), so we choose to include them. | ||
let include_remote_unknown_htlcs = true; | ||
let addl_nondust_htlc_count = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't we want to make sure the new commitment is able to handle a new non-dust HTLC being added?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes thank you ! How about just 1 additional HTLC here ? This parameter increases the commitment transaction fee we get back.
|
||
// TODO(splicing): Pre-check for reserve requirement | ||
// (Note: It should also be checked later at tx_complete) | ||
if their_funding_contribution.is_negative() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's also the case where we make a positive contribution and the counterparty does too, but a much larger one, bringing the reserve high enough that even after our contribution we still are not able to meet it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my reading of the spec, seems a party should only complain in cases where the counterparty's funding contribution is negative.
Did we want to be stricter than the spec here ?
let validate_stats = |stats: NextCommitmentStats| { | ||
let (_, remote_balance_incl_fee_msat) = stats.get_balances_including_fee_msat(); | ||
let splice_remote_balance_msat = remote_balance_incl_fee_msat | ||
.ok_or(ChannelError::Warn(format!("Remote balance does not cover the sum of HTLCs, anchors, and commitment transaction fee")))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error needs to be WarnAndDisconnect
|
||
// Reserve check on local commitment transaction | ||
|
||
let splice_local_commitment_stats = self.context.get_next_local_commitment_stats( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "next" naming is odd here because we're actually building an alternative version of the current commitment transaction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed :) If a squint a little, the "next" commitment transaction will have different to_local, to_remote balances, that's the one we are validating here. As far as I see at this point, this "alternative" commitment transaction is the one we will sign "next" ?
This is from 3921 feel free to take a look.
👋 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. |