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