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