@@ -5084,26 +5084,21 @@ where
50845084 pre_balance: u64, post_balance: u64, pre_channel_value: u64, post_channel_value: u64,
50855085 dust_limit: u64,
50865086 ) -> Result<(), u64> {
5087- if post_balance == 0 {
5088- // 0 balance is fine
5089- return Ok(());
5090- }
50915087 let post_channel_reserve = get_v2_channel_reserve_satoshis(post_channel_value, dust_limit);
50925088 if post_balance >= post_channel_reserve {
50935089 return Ok(());
50945090 }
5095- // post is not OK, check pre
5096- if pre_balance == 0 {
5097- // pre OK, post not -> not
5098- return Err(post_channel_reserve);
5099- }
51005091 let pre_channel_reserve = get_v2_channel_reserve_satoshis(pre_channel_value, dust_limit);
51015092 if pre_balance >= pre_channel_reserve {
5102- // pre OK, post not -> not
5093+ // We're not allowed to dip below the reserve once we've been above.
51035094 return Err(post_channel_reserve);
51045095 }
5105- // post not OK, but so was pre -> OK
5106- Ok(())
5096+ // Make sure we either remain with the same balance or move towards the reserve.
5097+ if post_balance >= pre_balance {
5098+ Ok(())
5099+ } else {
5100+ Err(post_channel_reserve)
5101+ }
51075102 }
51085103
51095104 /// Check that balances meet the channel reserve requirements or violates them (below reserve).
@@ -10916,6 +10911,71 @@ where
1091610911 })
1091710912 }
1091810913
10914+ /// Compute the channel balances (local & remote) by taking into account fees, anchor values, and dust limits.
10915+ /// Pending HTLCs are not taken into account, this method should be used when there is no such,
10916+ /// e.g. in quiscence state
10917+ #[cfg(splicing)]
10918+ fn compute_balances_less_fees(
10919+ &self, channel_value_sats: u64, value_to_self_msat: u64, is_local: bool,
10920+ ) -> (u64, u64) {
10921+ // We should get here only when there are no pending HTLCs, as they are not taken into account
10922+ debug_assert!(self.context.pending_inbound_htlcs.is_empty());
10923+ debug_assert!(self.context.pending_outbound_htlcs.is_empty());
10924+
10925+ let feerate_per_kw = self.context.feerate_per_kw;
10926+
10927+ // compute 'raw' counterparty balance
10928+ let value_to_remote_msat: i64 =
10929+ ((channel_value_sats * 1000) as i64).saturating_sub(value_to_self_msat as i64);
10930+ debug_assert!(value_to_remote_msat >= 0);
10931+
10932+ let total_fee_sat = SpecTxBuilder {}.commit_tx_fee_sat(
10933+ feerate_per_kw,
10934+ 0,
10935+ &self.funding.channel_transaction_parameters.channel_type_features,
10936+ );
10937+ let anchors_val = if self
10938+ .funding
10939+ .channel_transaction_parameters
10940+ .channel_type_features
10941+ .supports_anchors_zero_fee_htlc_tx()
10942+ {
10943+ ANCHOR_OUTPUT_VALUE_SATOSHI * 2
10944+ } else {
10945+ 0
10946+ } as i64;
10947+
10948+ // consider fees and anchor values
10949+ let (mut value_to_self, mut value_to_remote) = if self.funding.is_outbound() {
10950+ (
10951+ (value_to_self_msat as i64) / 1000 - anchors_val - total_fee_sat as i64,
10952+ value_to_remote_msat / 1000,
10953+ )
10954+ } else {
10955+ (
10956+ (value_to_self_msat as i64) / 1000,
10957+ value_to_remote_msat / 1000 - anchors_val - total_fee_sat as i64,
10958+ )
10959+ };
10960+
10961+ // consider dust limit
10962+ let broadcaster_dust_limit_satoshis = if is_local {
10963+ self.context.holder_dust_limit_satoshis
10964+ } else {
10965+ self.context.counterparty_dust_limit_satoshis
10966+ } as i64;
10967+ if value_to_self < broadcaster_dust_limit_satoshis {
10968+ value_to_self = 0;
10969+ }
10970+ debug_assert!(value_to_self >= 0);
10971+ if value_to_remote < broadcaster_dust_limit_satoshis {
10972+ value_to_remote = 0;
10973+ }
10974+ debug_assert!(value_to_remote >= 0);
10975+
10976+ (value_to_self as u64, value_to_remote as u64)
10977+ }
10978+
1091910979 /// Handle splice_ack
1092010980 #[cfg(splicing)]
1092110981 pub(crate) fn splice_ack<ES: Deref, L: Deref>(
@@ -10926,35 +10986,37 @@ where
1092610986 ES::Target: EntropySource,
1092710987 L::Target: Logger,
1092810988 {
10929- let pending_splice = if let Some(ref mut pending_splice) = &mut self.pending_splice {
10930- pending_splice
10931- } else {
10932- return Err(ChannelError::Ignore(format!("Channel is not in pending splice")));
10933- };
10989+ let funding_negotiation_context = {
10990+ let pending_splice = if let Some(ref mut pending_splice) = &mut self.pending_splice {
10991+ pending_splice
10992+ } else {
10993+ return Err(ChannelError::Ignore(format!("Channel is not in pending splice")));
10994+ };
1093410995
10935- // TODO(splicing): Add check that we are the splice (quiescence) initiator
10996+ // TODO(splicing): Add check that we are the splice (quiescence) initiator
1093610997
10937- let funding_negotiation_context = match pending_splice.funding_negotiation.take() {
10938- Some(FundingNegotiation::AwaitingAck(context)) => context,
10939- Some(FundingNegotiation::ConstructingTransaction(funding, constructor)) => {
10940- pending_splice.funding_negotiation =
10941- Some(FundingNegotiation::ConstructingTransaction(funding, constructor));
10942- return Err(ChannelError::WarnAndDisconnect(format!(
10943- "Got unexpected splice_ack; splice negotiation already in progress"
10944- )));
10945- },
10946- Some(FundingNegotiation::AwaitingSignatures(funding)) => {
10947- pending_splice.funding_negotiation =
10948- Some(FundingNegotiation::AwaitingSignatures(funding));
10949- return Err(ChannelError::WarnAndDisconnect(format!(
10950- "Got unexpected splice_ack; splice negotiation already in progress"
10951- )));
10952- },
10953- None => {
10954- return Err(ChannelError::Ignore(format!(
10955- "Got unexpected splice_ack; no splice negotiation in progress"
10956- )));
10957- },
10998+ match pending_splice.funding_negotiation.take() {
10999+ Some(FundingNegotiation::AwaitingAck(context)) => context,
11000+ Some(FundingNegotiation::ConstructingTransaction(funding, constructor)) => {
11001+ pending_splice.funding_negotiation =
11002+ Some(FundingNegotiation::ConstructingTransaction(funding, constructor));
11003+ return Err(ChannelError::WarnAndDisconnect(format!(
11004+ "Got unexpected splice_ack; splice negotiation already in progress"
11005+ )));
11006+ },
11007+ Some(FundingNegotiation::AwaitingSignatures(funding)) => {
11008+ pending_splice.funding_negotiation =
11009+ Some(FundingNegotiation::AwaitingSignatures(funding));
11010+ return Err(ChannelError::WarnAndDisconnect(format!(
11011+ "Got unexpected splice_ack; splice negotiation already in progress"
11012+ )));
11013+ },
11014+ None => {
11015+ return Err(ChannelError::Ignore(format!(
11016+ "Got unexpected splice_ack; no splice negotiation in progress"
11017+ )));
11018+ },
11019+ }
1095811020 };
1095911021
1096011022 let our_funding_contribution_satoshis =
@@ -10979,15 +11041,17 @@ where
1097911041 let pre_balance_self = self.funding.value_to_self_msat;
1098011042 let post_balance_self =
1098111043 PendingSplice::add_checked(pre_balance_self, our_funding_contribution_satoshis);
10982- let pre_balance_counterparty = pre_channel_value.saturating_sub(pre_balance_self);
10983- let post_balance_counterparty = post_channel_value.saturating_sub(post_balance_self);
11044+ let (pre_balance_self_less_fees, pre_balance_counterparty_less_fees) =
11045+ self.compute_balances_less_fees(pre_channel_value, pre_balance_self, true);
11046+ let (post_balance_self_less_fees, post_balance_counterparty_less_fees) =
11047+ self.compute_balances_less_fees(post_channel_value, post_balance_self, true);
1098411048 // Pre-check for reserve requirement
1098511049 // This will also be checked later at tx_complete
1098611050 let _res = self.context.check_splice_balances_meet_v2_reserve_requirements(
10987- pre_balance_self ,
10988- post_balance_self ,
10989- pre_balance_counterparty ,
10990- post_balance_counterparty ,
11051+ pre_balance_self_less_fees ,
11052+ post_balance_self_less_fees ,
11053+ pre_balance_counterparty_less_fees ,
11054+ post_balance_counterparty_less_fees ,
1099111055 pre_channel_value,
1099211056 post_channel_value,
1099311057 )?;
@@ -11017,6 +11081,11 @@ where
1101711081 let tx_msg_opt = interactive_tx_constructor.take_initiator_first_message();
1101811082
1101911083 debug_assert!(self.interactive_tx_signing_session.is_none());
11084+ let pending_splice = if let Some(ref mut pending_splice) = &mut self.pending_splice {
11085+ pending_splice
11086+ } else {
11087+ return Err(ChannelError::Ignore(format!("Channel is not in pending splice")));
11088+ };
1102011089 pending_splice.funding_negotiation = Some(FundingNegotiation::ConstructingTransaction(
1102111090 splice_funding,
1102211091 interactive_tx_constructor,
0 commit comments