Skip to content

Commit 1687505

Browse files
committed
Improve error handling, persistence; misc review changes
1 parent 4f8594e commit 1687505

File tree

4 files changed

+112
-147
lines changed

4 files changed

+112
-147
lines changed

lightning/src/ln/channel.rs

Lines changed: 48 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -4129,33 +4129,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
41294129
}
41304130
}
41314131

4132-
/// Check that a balance value meets the channel reserve requirements or violates them (below reserve).
4133-
/// The channel value is an input as opposed to using from self, so that this can be used in case of splicing
4134-
/// to checks with new channel value (before being comitted to it).
4135-
#[cfg(splicing)]
4136-
pub fn check_balance_meets_reserve_requirements(&self, balance: u64, channel_value: u64) -> Result<(), ChannelError> {
4137-
if balance == 0 {
4138-
return Ok(());
4139-
}
4140-
let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
4141-
channel_value, self.holder_dust_limit_satoshis);
4142-
if balance < holder_selected_channel_reserve_satoshis {
4143-
return Err(ChannelError::Warn(format!(
4144-
"Balance below reserve mandated by holder, {} vs {}",
4145-
balance, holder_selected_channel_reserve_satoshis,
4146-
)));
4147-
}
4148-
let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
4149-
channel_value, self.counterparty_dust_limit_satoshis);
4150-
if balance < counterparty_selected_channel_reserve_satoshis {
4151-
return Err(ChannelError::Warn(format!(
4152-
"Balance below reserve mandated by counterparty, {} vs {}",
4153-
balance, counterparty_selected_channel_reserve_satoshis,
4154-
)));
4155-
}
4156-
Ok(())
4157-
}
4158-
41594132
/// Get the commitment tx fee for the local's (i.e. our) next commitment transaction based on the
41604133
/// number of pending HTLCs that are on track to be in our next commitment tx.
41614134
///
@@ -8377,74 +8350,66 @@ impl<SP: Deref> FundedChannel<SP> where
83778350
}
83788351
}
83798352

8380-
/// Initiate splicing
8353+
/// Initiate splicing.
8354+
/// - our_funding_inputs: the inputs we contribute to the new funding transaction.
8355+
/// Includes the witness weight for this input (e.g. P2WPKH_WITNESS_WEIGHT=109 for typical P2WPKH inputs).
83818356
#[cfg(splicing)]
83828357
pub fn splice_channel(&mut self, our_funding_contribution_satoshis: i64,
8383-
our_funding_inputs: Vec<(TxIn, Transaction, Weight)>, funding_feerate_perkw: u32, locktime: u32,
8384-
) -> Result<msgs::SpliceInit, ChannelError> {
8358+
_our_funding_inputs: &Vec<(TxIn, Transaction, Weight)>,
8359+
funding_feerate_per_kw: u32, locktime: u32,
8360+
) -> Result<msgs::SpliceInit, APIError> {
83858361
// Check if a splice has been initiated already.
8386-
// Note: this could be handled more nicely, and support multiple outstanding splice's, the incoming splice_ack matters anyways.
8362+
// Note: only a single outstanding splice is supported (per spec)
83878363
if let Some(splice_info) = &self.pending_splice_pre {
8388-
return Err(ChannelError::Warn(format!(
8389-
"Channel has already a splice pending, contribution {}", splice_info.our_funding_contribution
8390-
)));
8364+
return Err(APIError::APIMisuseError { err: format!(
8365+
"Channel {} cannot be spliced, as it has already a splice pending (contribution {})",
8366+
self.context.channel_id(), splice_info.our_funding_contribution
8367+
)});
83918368
}
83928369

8393-
if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
8394-
return Err(ChannelError::Warn(format!("Cannot initiate splicing, as channel is not Ready")));
8370+
if !self.context.is_live() {
8371+
return Err(APIError::APIMisuseError { err: format!(
8372+
"Channel {} cannot be spliced, as channel is not live",
8373+
self.context.channel_id()
8374+
)});
83958375
}
83968376

8397-
let pre_channel_value = self.funding.get_value_satoshis();
8398-
// Sanity check: capacity cannot decrease below 0
8399-
if (pre_channel_value as i64).saturating_add(our_funding_contribution_satoshis) < 0 {
8400-
return Err(ChannelError::Warn(format!(
8401-
"Post-splicing channel value cannot be negative. It was {} + {}",
8402-
pre_channel_value, our_funding_contribution_satoshis
8403-
)));
8404-
}
8377+
// TODO(splicing): check for quiescence
84058378

84068379
if our_funding_contribution_satoshis < 0 {
8407-
return Err(ChannelError::Warn(format!(
8408-
"TODO(splicing): Splice-out not supported, only splice in, contribution {}",
8409-
our_funding_contribution_satoshis,
8410-
)));
8380+
return Err(APIError::APIMisuseError { err: format!(
8381+
"TODO(splicing): Splice-out not supported, only splice in; channel ID {}, contribution {}",
8382+
self.context.channel_id(), our_funding_contribution_satoshis,
8383+
)});
84118384
}
84128385

8413-
// Note: post-splice channel value is not yet known at this point, counterpary contribution is not known
8386+
// TODO(splicing): Once splice-out is supported, check that channel balance does not go below 0
8387+
// (or below channel reserve)
8388+
8389+
// Note: post-splice channel value is not yet known at this point, counterparty contribution is not known
84148390
// (Cannot test for miminum required post-splice channel value)
84158391

8416-
// Check that inputs are sufficient to cover our contribution
8417-
let sum_input: i64 = our_funding_inputs.into_iter().map(
8418-
|(txin, tx, _)| tx.output.get(txin.previous_output.vout as usize).map(|tx| tx.value.to_sat() as i64).unwrap_or(0)
8419-
).sum();
8420-
if sum_input < our_funding_contribution_satoshis {
8421-
return Err(ChannelError::Warn(format!(
8422-
"Provided inputs are insufficient for our contribution, {} {}",
8423-
sum_input, our_funding_contribution_satoshis,
8424-
)));
8425-
}
84268392

84278393
self.pending_splice_pre = Some(PendingSplice {
84288394
our_funding_contribution: our_funding_contribution_satoshis,
84298395
});
84308396

8431-
let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_perkw, locktime);
8397+
let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw, locktime);
84328398
Ok(msg)
84338399
}
84348400

84358401
/// Get the splice message that can be sent during splice initiation.
84368402
#[cfg(splicing)]
84378403
pub fn get_splice_init(&self, our_funding_contribution_satoshis: i64,
8438-
funding_feerate_perkw: u32, locktime: u32,
8404+
funding_feerate_per_kw: u32, locktime: u32,
84398405
) -> msgs::SpliceInit {
8440-
// Reuse the existing funding pubkey, in spite of the channel value changing
8441-
// (though at this point we don't know the new value yet, due tue the optional counterparty contribution)
8406+
// TODO(splicing): The exisiting pubkey is reused, but a new one should be generated. See #3542.
84428407
// Note that channel_keys_id is supposed NOT to change
84438408
let funding_pubkey = self.funding.get_holder_pubkeys().funding_pubkey.clone();
84448409
msgs::SpliceInit {
84458410
channel_id: self.context.channel_id,
84468411
funding_contribution_satoshis: our_funding_contribution_satoshis,
8447-
funding_feerate_perkw,
8412+
funding_feerate_per_kw,
84488413
locktime,
84498414
funding_pubkey,
84508415
require_confirmed_inputs: None,
@@ -8466,20 +8431,11 @@ impl<SP: Deref> FundedChannel<SP> where
84668431
)));
84678432
}
84688433

8469-
if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
8470-
return Err(ChannelError::Warn(format!("Splicing requested on a channel that is not Ready")));
8471-
}
8472-
8473-
let pre_channel_value = self.funding.get_value_satoshis();
8474-
// Sanity check: capacity cannot decrease below 0
8475-
if (pre_channel_value as i64)
8476-
.saturating_add(their_funding_contribution_satoshis)
8477-
.saturating_add(our_funding_contribution_satoshis) < 0
8478-
{
8479-
return Err(ChannelError::Warn(format!(
8480-
"Post-splicing channel value cannot be negative. It was {} + {} + {}",
8481-
pre_channel_value, their_funding_contribution_satoshis, our_funding_contribution_satoshis,
8482-
)));
8434+
// - If it has received shutdown:
8435+
// MUST send a warning and close the connection or send an error
8436+
// and fail the channel.
8437+
if !self.context.is_live() {
8438+
return Err(ChannelError::Warn(format!("Splicing requested on a channel that is not live")));
84838439
}
84848440

84858441
if their_funding_contribution_satoshis.saturating_add(our_funding_contribution_satoshis) < 0 {
@@ -8489,11 +8445,12 @@ impl<SP: Deref> FundedChannel<SP> where
84898445
)));
84908446
}
84918447

8492-
let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, their_funding_contribution_satoshis, our_funding_contribution_satoshis);
8493-
let post_balance = PendingSplice::add_checked(self.funding.value_to_self_msat, our_funding_contribution_satoshis);
8494-
// Early check for reserve requirement, assuming maximum balance of full channel value
8495-
// This will also be checked later at tx_complete
8496-
let _res = self.context.check_balance_meets_reserve_requirements(post_balance, post_channel_value)?;
8448+
// TODO(splicing): Once splice acceptor can contribute, check that inputs are sufficient,
8449+
// similarly to the check in `splice_channel`.
8450+
8451+
// Note on channel reserve requirement pre-check: as the splice acceptor does not contribute,
8452+
// it can't go below reserve, therefore no pre-check is done here.
8453+
// TODO(splicing): Once splice acceptor can contribute, add reserve pre-check, similar to the one in `splice_ack`.
84978454

84988455
// TODO(splicing): Store msg.funding_pubkey
84998456
// TODO(splicing): Apply start of splice (splice_start)
@@ -8506,7 +8463,8 @@ impl<SP: Deref> FundedChannel<SP> where
85068463
/// Get the splice_ack message that can be sent in response to splice initiation.
85078464
#[cfg(splicing)]
85088465
pub fn get_splice_ack(&self, our_funding_contribution_satoshis: i64) -> msgs::SpliceAck {
8509-
// Reuse the existing funding pubkey, in spite of the channel value changing
8466+
// TODO(splicing): The exisiting pubkey is reused, but a new one should be generated. See #3542.
8467+
// Note that channel_keys_id is supposed NOT to change
85108468
let funding_pubkey = self.funding.get_holder_pubkeys().funding_pubkey;
85118469
msgs::SpliceAck {
85128470
channel_id: self.context.channel_id,
@@ -8518,24 +8476,14 @@ impl<SP: Deref> FundedChannel<SP> where
85188476

85198477
/// Handle splice_ack
85208478
#[cfg(splicing)]
8521-
pub fn splice_ack(&mut self, msg: &msgs::SpliceAck) -> Result<(), ChannelError> {
8522-
let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
8523-
8479+
pub fn splice_ack(&mut self, _msg: &msgs::SpliceAck) -> Result<(), ChannelError> {
85248480
// check if splice is pending
8525-
let pending_splice = if let Some(pending_splice) = &self.pending_splice_pre {
8526-
pending_splice
8527-
} else {
8481+
if self.pending_splice_pre.is_none() {
85288482
return Err(ChannelError::Warn(format!("Channel is not in pending splice")));
85298483
};
85308484

8531-
let our_funding_contribution = pending_splice.our_funding_contribution;
8532-
8533-
let pre_channel_value = self.funding.get_value_satoshis();
8534-
let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution_satoshis);
8535-
let post_balance = PendingSplice::add_checked(self.funding.value_to_self_msat, our_funding_contribution);
8536-
// Early check for reserve requirement, assuming maximum balance of full channel value
8537-
// This will also be checked later at tx_complete
8538-
let _res = self.context.check_balance_meets_reserve_requirements(post_balance, post_channel_value)?;
8485+
// TODO(splicing): Pre-check for reserve requirement
8486+
// (Note: It should also be checked later at tx_complete)
85398487
Ok(())
85408488
}
85418489

@@ -12906,15 +12854,15 @@ mod tests {
1290612854
);
1290712855
}
1290812856

12909-
#[cfg(all(test, splicing))]
12857+
#[cfg(splicing)]
1291012858
fn get_pre_and_post(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> (u64, u64) {
1291112859
use crate::ln::channel::PendingSplice;
1291212860

1291312861
let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution);
1291412862
(pre_channel_value, post_channel_value)
1291512863
}
1291612864

12917-
#[cfg(all(test, splicing))]
12865+
#[cfg(splicing)]
1291812866
#[test]
1291912867
fn test_splice_compute_post_value() {
1292012868
{

0 commit comments

Comments
 (0)