@@ -8377,74 +8377,66 @@ impl<SP: Deref> FundedChannel<SP> where
8377
8377
}
8378
8378
}
8379
8379
8380
- /// Initiate splicing
8380
+ /// Initiate splicing.
8381
+ /// - our_funding_inputs: the inputs we contribute to the new funding transaction.
8382
+ /// Includes the witness weight for this input (e.g. P2WPKH_WITNESS_WEIGHT=109 for typical P2WPKH inputs).
8381
8383
#[cfg(splicing)]
8382
8384
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> {
8385
+ _our_funding_inputs: &Vec<(TxIn, Transaction, Weight)>,
8386
+ funding_feerate_per_kw: u32, locktime: u32,
8387
+ ) -> Result<msgs::SpliceInit, APIError> {
8385
8388
// 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.
8389
+ // Note: only a single outstanding splice is supported (per spec)
8387
8390
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
- )));
8391
+ return Err(APIError::APIMisuseError { err: format!(
8392
+ "Channel {} cannot be spliced, as it has already a splice pending (contribution {})",
8393
+ self.context.channel_id(), splice_info.our_funding_contribution
8394
+ )});
8391
8395
}
8392
8396
8393
- if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
8394
- return Err(ChannelError::Warn(format!("Cannot initiate splicing, as channel is not Ready")));
8397
+ if !self.context.is_live() {
8398
+ return Err(APIError::APIMisuseError { err: format!(
8399
+ "Channel {} cannot be spliced, as channel is not live",
8400
+ self.context.channel_id()
8401
+ )});
8395
8402
}
8396
8403
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
- }
8404
+ // TODO(splicing): check for quiescence
8405
8405
8406
8406
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
- )) );
8407
+ return Err(APIError::APIMisuseError { err: format!(
8408
+ "TODO(splicing): Splice-out not supported, only splice in; channel ID {} , contribution {}",
8409
+ self.context.channel_id(), our_funding_contribution_satoshis,
8410
+ )} );
8411
8411
}
8412
8412
8413
- // Note: post-splice channel value is not yet known at this point, counterpary contribution is not known
8413
+ // TODO(splicing): Once splice-out is supported, check that channel balance does not go below 0
8414
+ // (or below channel reserve)
8415
+
8416
+ // Note: post-splice channel value is not yet known at this point, counterparty contribution is not known
8414
8417
// (Cannot test for miminum required post-splice channel value)
8415
8418
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
- }
8426
8419
8427
8420
self.pending_splice_pre = Some(PendingSplice {
8428
8421
our_funding_contribution: our_funding_contribution_satoshis,
8429
8422
});
8430
8423
8431
- let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_perkw , locktime);
8424
+ let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw , locktime);
8432
8425
Ok(msg)
8433
8426
}
8434
8427
8435
8428
/// Get the splice message that can be sent during splice initiation.
8436
8429
#[cfg(splicing)]
8437
8430
pub fn get_splice_init(&self, our_funding_contribution_satoshis: i64,
8438
- funding_feerate_perkw : u32, locktime: u32,
8431
+ funding_feerate_per_kw : u32, locktime: u32,
8439
8432
) -> 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)
8433
+ // TODO(splicing): The exisiting pubkey is reused, but a new one should be generated. See #3542.
8442
8434
// Note that channel_keys_id is supposed NOT to change
8443
8435
let funding_pubkey = self.funding.get_holder_pubkeys().funding_pubkey.clone();
8444
8436
msgs::SpliceInit {
8445
8437
channel_id: self.context.channel_id,
8446
8438
funding_contribution_satoshis: our_funding_contribution_satoshis,
8447
- funding_feerate_perkw ,
8439
+ funding_feerate_per_kw ,
8448
8440
locktime,
8449
8441
funding_pubkey,
8450
8442
require_confirmed_inputs: None,
@@ -8466,20 +8458,11 @@ impl<SP: Deref> FundedChannel<SP> where
8466
8458
)));
8467
8459
}
8468
8460
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
- )));
8461
+ // - If it has received shutdown:
8462
+ // MUST send a warning and close the connection or send an error
8463
+ // and fail the channel.
8464
+ if !self.context.is_live() {
8465
+ return Err(ChannelError::Warn(format!("Splicing requested on a channel that is not live")));
8483
8466
}
8484
8467
8485
8468
if their_funding_contribution_satoshis.saturating_add(our_funding_contribution_satoshis) < 0 {
@@ -8489,11 +8472,12 @@ impl<SP: Deref> FundedChannel<SP> where
8489
8472
)));
8490
8473
}
8491
8474
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)?;
8475
+ // TODO(splicing): Once splice acceptor can contribute, check that inputs are sufficient,
8476
+ // similarly to the check in `splice_channel`.
8477
+
8478
+ // Note on channel reserve requirement pre-check: as the splice acceptor does not contribute,
8479
+ // it can't go below reserve, therefore no pre-check is done here.
8480
+ // TODO(splicing): Once splice acceptor can contribute, add reserve pre-check, similar to the one in `splice_ack`.
8497
8481
8498
8482
// TODO(splicing): Store msg.funding_pubkey
8499
8483
// TODO(splicing): Apply start of splice (splice_start)
@@ -8506,7 +8490,8 @@ impl<SP: Deref> FundedChannel<SP> where
8506
8490
/// Get the splice_ack message that can be sent in response to splice initiation.
8507
8491
#[cfg(splicing)]
8508
8492
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
8493
+ // TODO(splicing): The exisiting pubkey is reused, but a new one should be generated. See #3542.
8494
+ // Note that channel_keys_id is supposed NOT to change
8510
8495
let funding_pubkey = self.funding.get_holder_pubkeys().funding_pubkey;
8511
8496
msgs::SpliceAck {
8512
8497
channel_id: self.context.channel_id,
@@ -12906,15 +12891,15 @@ mod tests {
12906
12891
);
12907
12892
}
12908
12893
12909
- #[cfg(all(test, splicing) )]
12894
+ #[cfg(splicing)]
12910
12895
fn get_pre_and_post(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> (u64, u64) {
12911
12896
use crate::ln::channel::PendingSplice;
12912
12897
12913
12898
let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution);
12914
12899
(pre_channel_value, post_channel_value)
12915
12900
}
12916
12901
12917
- #[cfg(all(test, splicing) )]
12902
+ #[cfg(splicing)]
12918
12903
#[test]
12919
12904
fn test_splice_compute_post_value() {
12920
12905
{
0 commit comments