Skip to content

Commit bc5ea6c

Browse files
committed
Improve error handling, persistence; misc review changes
1 parent cc5f4c2 commit bc5ea6c

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
@@ -4130,33 +4130,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
41304130
}
41314131
}
41324132

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

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

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

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

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

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

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

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

8432-
let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_perkw, locktime);
8398+
let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw, locktime);
84338399
Ok(msg)
84348400
}
84358401

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

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

84868442
if their_funding_contribution_satoshis.saturating_add(our_funding_contribution_satoshis) < 0 {
@@ -8490,11 +8446,12 @@ impl<SP: Deref> FundedChannel<SP> where
84908446
)));
84918447
}
84928448

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

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

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

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

@@ -12907,15 +12855,15 @@ mod tests {
1290712855
);
1290812856
}
1290912857

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

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

12918-
#[cfg(all(test, splicing))]
12866+
#[cfg(splicing)]
1291912867
#[test]
1292012868
fn test_splice_compute_post_value() {
1292112869
{

0 commit comments

Comments
 (0)