@@ -26,7 +26,7 @@ use bitcoin::secp256k1::{ecdsa::Signature, Secp256k1};
26
26
use bitcoin::secp256k1::{PublicKey, SecretKey};
27
27
use bitcoin::{secp256k1, sighash};
28
28
#[cfg(splicing)]
29
- use bitcoin::{Sequence, TxIn};
29
+ use bitcoin::{FeeRate, Sequence, TxIn};
30
30
31
31
use crate::chain::chaininterface::{
32
32
fee_for_weight, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator,
@@ -5878,6 +5878,40 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
5878
5878
cmp::min(channel_value_satoshis, cmp::max(q, dust_limit_satoshis))
5879
5879
}
5880
5880
5881
+ #[cfg(splicing)]
5882
+ fn check_splice_contribution_sufficient(
5883
+ channel_balance: Amount, contribution: &SpliceContribution, is_initiator: bool,
5884
+ funding_feerate: FeeRate,
5885
+ ) -> Result<Amount, ChannelError> {
5886
+ let contribution_amount = contribution.value();
5887
+ if contribution_amount < SignedAmount::ZERO {
5888
+ let estimated_fee = Amount::from_sat(estimate_v2_funding_transaction_fee(
5889
+ is_initiator,
5890
+ 1, // spends the previous funding output
5891
+ Weight::from_wu(FUNDING_TRANSACTION_WITNESS_WEIGHT),
5892
+ funding_feerate.to_sat_per_kwu() as u32,
5893
+ ));
5894
+
5895
+ if channel_balance > contribution_amount.unsigned_abs() + estimated_fee {
5896
+ Ok(estimated_fee)
5897
+ } else {
5898
+ Err(ChannelError::Warn(format!(
5899
+ "Available channel balance {} is lower than needed for splicing out {}, considering fees of {}",
5900
+ channel_balance, contribution_amount.unsigned_abs(), estimated_fee,
5901
+ )))
5902
+ }
5903
+ } else {
5904
+ check_v2_funding_inputs_sufficient(
5905
+ contribution_amount.to_sat(),
5906
+ contribution.inputs(),
5907
+ is_initiator,
5908
+ true,
5909
+ funding_feerate.to_sat_per_kwu() as u32,
5910
+ )
5911
+ .map(Amount::from_sat)
5912
+ }
5913
+ }
5914
+
5881
5915
/// Estimate our part of the fee of the new funding transaction.
5882
5916
/// input_count: Number of contributed inputs.
5883
5917
/// witness_weight: The witness weight for contributed inputs.
@@ -10671,42 +10705,48 @@ where
10671
10705
});
10672
10706
}
10673
10707
10674
- if our_funding_contribution < SignedAmount::ZERO {
10675
- // TODO(splicing): Check that channel balance does not go below the channel reserve
10676
- let post_channel_value = AddSigned::checked_add_signed(
10677
- self.funding.get_value_to_self_msat() / 1000,
10678
- our_funding_contribution.to_sat(),
10679
- );
10680
- // FIXME: Check that we can pay for the outputs from the channel value?
10681
- if post_channel_value.is_none() {
10682
- return Err(APIError::APIMisuseError {
10683
- err: format!(
10684
- "Channel {} cannot be spliced out; contribution exceeds the channel value: {}",
10685
- self.context.channel_id(),
10686
- our_funding_contribution,
10687
- ),
10688
- });
10689
- }
10690
- } else {
10691
- // Note: post-splice channel value is not yet known at this point, counterparty contribution is not known
10692
- // (Cannot test for miminum required post-splice channel value)
10708
+ // Note: post-splice channel value is not yet known at this point, counterparty contribution is not known
10709
+ // (Cannot test for miminum required post-splice channel value)
10693
10710
10694
- // Check that inputs are sufficient to cover our contribution.
10695
- let _fee = check_v2_funding_inputs_sufficient(
10696
- our_funding_contribution.to_sat(),
10697
- contribution.inputs(),
10698
- true,
10699
- true,
10700
- funding_feerate_per_kw,
10701
- )
10702
- .map_err(|err| APIError::APIMisuseError {
10711
+ let channel_balance = Amount::from_sat(self.funding.get_value_to_self_msat() / 1000);
10712
+ let fees = check_splice_contribution_sufficient(
10713
+ channel_balance,
10714
+ &contribution,
10715
+ true, // is_initiator
10716
+ FeeRate::from_sat_per_kwu(funding_feerate_per_kw as u64),
10717
+ )
10718
+ .map_err(|e| {
10719
+ let splice_type = if our_funding_contribution < SignedAmount::ZERO {
10720
+ "spliced out"
10721
+ } else {
10722
+ "spliced in"
10723
+ };
10724
+ APIError::APIMisuseError {
10703
10725
err: format!(
10704
- "Insufficient inputs for splicing; channel ID {}, err {}",
10726
+ "Channel {} cannot be {}; {}",
10705
10727
self.context.channel_id(),
10706
- err,
10728
+ splice_type,
10729
+ e,
10707
10730
),
10708
- })?;
10709
- }
10731
+ }
10732
+ })?;
10733
+
10734
+ // Fees for splice-out are paid from the channel balance whereas fees for splice-in are paid
10735
+ // by the funding inputs.
10736
+ let adjusted_funding_contribution = if our_funding_contribution < SignedAmount::ZERO {
10737
+ let adjusted_funding_contribution = our_funding_contribution
10738
+ + fees.to_signed().expect("fees should never exceed splice-out value");
10739
+
10740
+ // TODO(splicing): Check that channel balance does not go below the channel reserve
10741
+ let _post_channel_balance = AddSigned::checked_add_signed(
10742
+ channel_balance.to_sat(),
10743
+ adjusted_funding_contribution.to_sat(),
10744
+ );
10745
+
10746
+ adjusted_funding_contribution
10747
+ } else {
10748
+ our_funding_contribution
10749
+ };
10710
10750
10711
10751
for FundingTxInput { txin, prevtx, .. } in contribution.inputs().iter() {
10712
10752
const MESSAGE_TEMPLATE: msgs::TxAddInput = msgs::TxAddInput {
@@ -10732,7 +10772,7 @@ where
10732
10772
let (our_funding_inputs, our_funding_outputs, change_script) = contribution.into_tx_parts();
10733
10773
let funding_negotiation_context = FundingNegotiationContext {
10734
10774
is_initiator: true,
10735
- our_funding_contribution,
10775
+ our_funding_contribution: adjusted_funding_contribution ,
10736
10776
funding_tx_locktime: LockTime::from_consensus(locktime),
10737
10777
funding_feerate_sat_per_1000_weight: funding_feerate_per_kw,
10738
10778
shared_funding_input: Some(prev_funding_input),
0 commit comments