Skip to content

Commit 425a978

Browse files
committed
Consider fees and anchor in balances when checking reserve requirements
1 parent fe1deec commit 425a978

File tree

1 file changed

+101
-33
lines changed

1 file changed

+101
-33
lines changed

lightning/src/ln/channel.rs

Lines changed: 101 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10916,6 +10916,65 @@ where
1091610916
})
1091710917
}
1091810918

10919+
/// Compute the channel balances (local & remote) by taking into account fees, anchor values, and dust limits.
10920+
#[cfg(splicing)]
10921+
fn compute_balances_less_fees(
10922+
&self, channel_value_sats: u64, value_to_self_msat: u64, is_local: bool,
10923+
) -> (u64, u64) {
10924+
let feerate_per_kw = self.context.feerate_per_kw;
10925+
10926+
// compute 'raw' counterparty balance
10927+
let value_to_remote_msat: i64 =
10928+
((channel_value_sats * 1000) as i64).saturating_sub(value_to_self_msat as i64);
10929+
debug_assert!(value_to_remote_msat >= 0);
10930+
10931+
let total_fee_sat = SpecTxBuilder {}.commit_tx_fee_sat(
10932+
feerate_per_kw,
10933+
0,
10934+
&self.funding.channel_transaction_parameters.channel_type_features,
10935+
);
10936+
let anchors_val = if self
10937+
.funding
10938+
.channel_transaction_parameters
10939+
.channel_type_features
10940+
.supports_anchors_zero_fee_htlc_tx()
10941+
{
10942+
ANCHOR_OUTPUT_VALUE_SATOSHI * 2
10943+
} else {
10944+
0
10945+
} as i64;
10946+
10947+
// consider fees and anchor values
10948+
let (mut value_to_self, mut value_to_remote) = if self.funding.is_outbound() {
10949+
(
10950+
(value_to_self_msat as i64) / 1000 - anchors_val - total_fee_sat as i64,
10951+
value_to_remote_msat / 1000,
10952+
)
10953+
} else {
10954+
(
10955+
(value_to_self_msat as i64) / 1000,
10956+
value_to_remote_msat / 1000 - anchors_val - total_fee_sat as i64,
10957+
)
10958+
};
10959+
10960+
// consider dust limit
10961+
let broadcaster_dust_limit_satoshis = if is_local {
10962+
self.context.holder_dust_limit_satoshis
10963+
} else {
10964+
self.context.counterparty_dust_limit_satoshis
10965+
} as i64;
10966+
if value_to_self < broadcaster_dust_limit_satoshis {
10967+
value_to_self = 0;
10968+
}
10969+
debug_assert!(value_to_self >= 0);
10970+
if value_to_remote < broadcaster_dust_limit_satoshis {
10971+
value_to_remote = 0;
10972+
}
10973+
debug_assert!(value_to_remote >= 0);
10974+
10975+
(value_to_self as u64, value_to_remote as u64)
10976+
}
10977+
1091910978
/// Handle splice_ack
1092010979
#[cfg(splicing)]
1092110980
pub(crate) fn splice_ack<ES: Deref, L: Deref>(
@@ -10926,35 +10985,37 @@ where
1092610985
ES::Target: EntropySource,
1092710986
L::Target: Logger,
1092810987
{
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-
};
10988+
let funding_negotiation_context = {
10989+
let pending_splice = if let Some(ref mut pending_splice) = &mut self.pending_splice {
10990+
pending_splice
10991+
} else {
10992+
return Err(ChannelError::Ignore(format!("Channel is not in pending splice")));
10993+
};
1093410994

10935-
// TODO(splicing): Add check that we are the splice (quiescence) initiator
10995+
// TODO(splicing): Add check that we are the splice (quiescence) initiator
1093610996

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-
},
10997+
match pending_splice.funding_negotiation.take() {
10998+
Some(FundingNegotiation::AwaitingAck(context)) => context,
10999+
Some(FundingNegotiation::ConstructingTransaction(funding, constructor)) => {
11000+
pending_splice.funding_negotiation =
11001+
Some(FundingNegotiation::ConstructingTransaction(funding, constructor));
11002+
return Err(ChannelError::WarnAndDisconnect(format!(
11003+
"Got unexpected splice_ack; splice negotiation already in progress"
11004+
)));
11005+
},
11006+
Some(FundingNegotiation::AwaitingSignatures(funding)) => {
11007+
pending_splice.funding_negotiation =
11008+
Some(FundingNegotiation::AwaitingSignatures(funding));
11009+
return Err(ChannelError::WarnAndDisconnect(format!(
11010+
"Got unexpected splice_ack; splice negotiation already in progress"
11011+
)));
11012+
},
11013+
None => {
11014+
return Err(ChannelError::Ignore(format!(
11015+
"Got unexpected splice_ack; no splice negotiation in progress"
11016+
)));
11017+
},
11018+
}
1095811019
};
1095911020

1096011021
let our_funding_contribution_satoshis =
@@ -10979,15 +11040,17 @@ where
1097911040
let pre_balance_self = self.funding.value_to_self_msat;
1098011041
let post_balance_self =
1098111042
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);
11043+
let (pre_balance_self_less_fees, pre_balance_counterparty_less_fees) =
11044+
self.compute_balances_less_fees(pre_channel_value, pre_balance_self, true);
11045+
let (post_balance_self_less_fees, post_balance_counterparty_less_fees) =
11046+
self.compute_balances_less_fees(post_channel_value, post_balance_self, true);
1098411047
// Pre-check for reserve requirement
1098511048
// This will also be checked later at tx_complete
1098611049
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,
11050+
pre_balance_self_less_fees,
11051+
post_balance_self_less_fees,
11052+
pre_balance_counterparty_less_fees,
11053+
post_balance_counterparty_less_fees,
1099111054
pre_channel_value,
1099211055
post_channel_value,
1099311056
)?;
@@ -11017,6 +11080,11 @@ where
1101711080
let tx_msg_opt = interactive_tx_constructor.take_initiator_first_message();
1101811081

1101911082
debug_assert!(self.interactive_tx_signing_session.is_none());
11083+
let pending_splice = if let Some(ref mut pending_splice) = &mut self.pending_splice {
11084+
pending_splice
11085+
} else {
11086+
return Err(ChannelError::Ignore(format!("Channel is not in pending splice")));
11087+
};
1102011088
pending_splice.funding_negotiation = Some(FundingNegotiation::ConstructingTransaction(
1102111089
splice_funding,
1102211090
interactive_tx_constructor,

0 commit comments

Comments
 (0)