Skip to content

Commit fe1deec

Browse files
committed
Add check for channel reserve
1 parent 1e1d300 commit fe1deec

File tree

1 file changed

+108
-1
lines changed

1 file changed

+108
-1
lines changed

lightning/src/ln/channel.rs

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2477,6 +2477,28 @@ impl<'a> From<&'a Transaction> for ConfirmedTransaction<'a> {
24772477
}
24782478
}
24792479

2480+
#[cfg(splicing)]
2481+
impl PendingSplice {
2482+
#[inline]
2483+
fn add_checked(base: u64, delta: i64) -> u64 {
2484+
if delta >= 0 {
2485+
base.saturating_add(delta as u64)
2486+
} else {
2487+
base.saturating_sub(delta.abs() as u64)
2488+
}
2489+
}
2490+
2491+
// /// Compute the post-splice channel value from the pre-splice values and the peer contributions
2492+
// pub fn compute_post_splice_value(
2493+
// pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64,
2494+
// ) -> u64 {
2495+
// Self::add_checked(
2496+
// pre_channel_value,
2497+
// our_funding_contribution.saturating_add(their_funding_contribution),
2498+
// )
2499+
// }
2500+
}
2501+
24802502
/// Contains everything about the channel including state, and various flags.
24812503
pub(super) struct ChannelContext<SP: Deref>
24822504
where
@@ -5056,6 +5078,71 @@ where
50565078
}
50575079
}
50585080

5081+
/// Check that post-splicing balance meets reserve requirements, but only if it met it pre-splice as well
5082+
#[cfg(splicing)]
5083+
pub fn check_splice_balance_meets_v2_reserve_requirement_noerr(
5084+
pre_balance: u64, post_balance: u64, pre_channel_value: u64, post_channel_value: u64,
5085+
dust_limit: u64,
5086+
) -> Result<(), u64> {
5087+
if post_balance == 0 {
5088+
// 0 balance is fine
5089+
return Ok(());
5090+
}
5091+
let post_channel_reserve = get_v2_channel_reserve_satoshis(post_channel_value, dust_limit);
5092+
if post_balance >= post_channel_reserve {
5093+
return Ok(());
5094+
}
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+
}
5100+
let pre_channel_reserve = get_v2_channel_reserve_satoshis(pre_channel_value, dust_limit);
5101+
if pre_balance >= pre_channel_reserve {
5102+
// pre OK, post not -> not
5103+
return Err(post_channel_reserve);
5104+
}
5105+
// post not OK, but so was pre -> OK
5106+
Ok(())
5107+
}
5108+
5109+
/// Check that balances meet the channel reserve requirements or violates them (below reserve).
5110+
/// The channel value is an input as opposed to using from the FundingScope, so that this can be used in case of splicing
5111+
/// to check with new channel value (before being committed to it).
5112+
#[cfg(splicing)]
5113+
pub fn check_splice_balances_meet_v2_reserve_requirements(
5114+
&self, self_balance_pre: u64, self_balance_post: u64, counterparty_balance_pre: u64,
5115+
counterparty_balance_post: u64, channel_value_pre: u64, channel_value_post: u64,
5116+
) -> Result<(), ChannelError> {
5117+
let is_ok_self = Self::check_splice_balance_meets_v2_reserve_requirement_noerr(
5118+
self_balance_pre,
5119+
self_balance_post,
5120+
channel_value_pre,
5121+
channel_value_post,
5122+
self.holder_dust_limit_satoshis,
5123+
);
5124+
if let Err(channel_reserve_self) = is_ok_self {
5125+
return Err(ChannelError::Warn(format!(
5126+
"Balance below reserve, mandated by holder, {} vs {}",
5127+
self_balance_post, channel_reserve_self,
5128+
)));
5129+
}
5130+
let is_ok_cp = Self::check_splice_balance_meets_v2_reserve_requirement_noerr(
5131+
counterparty_balance_pre,
5132+
counterparty_balance_post,
5133+
channel_value_pre,
5134+
channel_value_post,
5135+
self.counterparty_dust_limit_satoshis,
5136+
);
5137+
if let Err(channel_reserve_cp) = is_ok_cp {
5138+
return Err(ChannelError::Warn(format!(
5139+
"Balance below reserve mandated by counterparty, {} vs {}",
5140+
counterparty_balance_post, channel_reserve_cp,
5141+
)));
5142+
}
5143+
Ok(())
5144+
}
5145+
50595146
/// Get the commitment tx fee for the local's (i.e. our) next commitment transaction based on the
50605147
/// number of pending HTLCs that are on track to be in our next commitment tx.
50615148
///
@@ -10882,8 +10969,28 @@ where
1088210969
msg.funding_pubkey,
1088310970
)?;
1088410971

10885-
// TODO(splicing): Pre-check for reserve requirement
10972+
// Pre-check for reserve requirement
1088610973
// (Note: It should also be checked later at tx_complete)
10974+
let pre_channel_value = self.funding.get_value_satoshis();
10975+
let post_channel_value = self.funding.compute_post_splice_value(
10976+
our_funding_contribution_satoshis,
10977+
their_funding_contribution_satoshis,
10978+
);
10979+
let pre_balance_self = self.funding.value_to_self_msat;
10980+
let post_balance_self =
10981+
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);
10984+
// Pre-check for reserve requirement
10985+
// This will also be checked later at tx_complete
10986+
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,
10991+
pre_channel_value,
10992+
post_channel_value,
10993+
)?;
1088710994

1088810995
log_info!(
1088910996
logger,

0 commit comments

Comments
 (0)