8
8
// licenses.
9
9
10
10
use bitcoin::absolute::LockTime;
11
- use bitcoin::amount::Amount;
11
+ use bitcoin::amount::{ Amount, SignedAmount} ;
12
12
use bitcoin::consensus::encode;
13
13
use bitcoin::constants::ChainHash;
14
14
use bitcoin::script::{Builder, Script, ScriptBuf, WScriptHash};
@@ -2244,20 +2244,22 @@ impl FundingScope {
2244
2244
/// Constructs a `FundingScope` for splicing a channel.
2245
2245
#[cfg(splicing)]
2246
2246
fn for_splice<SP: Deref>(
2247
- prev_funding: &Self, context: &ChannelContext<SP>, our_funding_contribution_sats: i64 ,
2248
- their_funding_contribution_sats: i64 , counterparty_funding_pubkey: PublicKey,
2247
+ prev_funding: &Self, context: &ChannelContext<SP>, our_funding_contribution: SignedAmount ,
2248
+ their_funding_contribution: SignedAmount , counterparty_funding_pubkey: PublicKey,
2249
2249
) -> Result<Self, ChannelError>
2250
2250
where
2251
2251
SP::Target: SignerProvider,
2252
2252
{
2253
+ debug_assert!(our_funding_contribution <= SignedAmount::MAX_MONEY);
2254
+
2253
2255
let post_channel_value = prev_funding.compute_post_splice_value(
2254
- our_funding_contribution_sats ,
2255
- their_funding_contribution_sats ,
2256
+ our_funding_contribution.to_sat() ,
2257
+ their_funding_contribution.to_sat() ,
2256
2258
);
2257
2259
2258
2260
let post_value_to_self_msat = AddSigned::checked_add_signed(
2259
2261
prev_funding.value_to_self_msat,
2260
- our_funding_contribution_sats * 1000,
2262
+ our_funding_contribution.to_sat() * 1000,
2261
2263
);
2262
2264
debug_assert!(post_value_to_self_msat.is_some());
2263
2265
let post_value_to_self_msat = post_value_to_self_msat.unwrap();
@@ -5964,7 +5966,7 @@ pub(super) struct FundingNegotiationContext {
5964
5966
/// Whether we initiated the funding negotiation.
5965
5967
pub is_initiator: bool,
5966
5968
/// The amount in satoshis we will be contributing to the channel.
5967
- pub our_funding_contribution_satoshis: i64 ,
5969
+ pub our_funding_contribution: SignedAmount ,
5968
5970
/// The amount in satoshis our counterparty will be contributing to the channel.
5969
5971
#[allow(dead_code)] // TODO(dual_funding): Remove once contribution to V2 channels is enabled.
5970
5972
pub their_funding_contribution_satoshis: Option<i64>,
@@ -6020,7 +6022,7 @@ impl FundingNegotiationContext {
6020
6022
};
6021
6023
6022
6024
// Optionally add change output
6023
- if self.our_funding_contribution_satoshis > 0 {
6025
+ if self.our_funding_contribution > SignedAmount::ZERO {
6024
6026
let change_value_opt = calculate_change_output_value(
6025
6027
&self,
6026
6028
self.shared_funding_input.is_some(),
@@ -10628,11 +10630,22 @@ where
10628
10630
10629
10631
// TODO(splicing): check for quiescence
10630
10632
10631
- if our_funding_contribution_satoshis < 0 {
10633
+ let our_funding_contribution = SignedAmount::from_sat(our_funding_contribution_satoshis);
10634
+ if our_funding_contribution > SignedAmount::MAX_MONEY {
10635
+ return Err(APIError::APIMisuseError {
10636
+ err: format!(
10637
+ "Channel {} cannot be spliced; contribution exceeds total bitcoin supply: {}",
10638
+ self.context.channel_id(),
10639
+ our_funding_contribution,
10640
+ ),
10641
+ });
10642
+ }
10643
+
10644
+ if our_funding_contribution < SignedAmount::ZERO {
10632
10645
return Err(APIError::APIMisuseError {
10633
10646
err: format!(
10634
10647
"TODO(splicing): Splice-out not supported, only splice in; channel ID {}, contribution {}",
10635
- self.context.channel_id(), our_funding_contribution_satoshis ,
10648
+ self.context.channel_id(), our_funding_contribution ,
10636
10649
),
10637
10650
});
10638
10651
}
@@ -10645,7 +10658,7 @@ where
10645
10658
10646
10659
// Check that inputs are sufficient to cover our contribution.
10647
10660
let _fee = check_v2_funding_inputs_sufficient(
10648
- our_funding_contribution_satoshis ,
10661
+ our_funding_contribution.to_sat() ,
10649
10662
&our_funding_inputs,
10650
10663
true,
10651
10664
true,
@@ -10669,7 +10682,7 @@ where
10669
10682
let prev_funding_input = self.funding.to_splice_funding_input();
10670
10683
let funding_negotiation_context = FundingNegotiationContext {
10671
10684
is_initiator: true,
10672
- our_funding_contribution_satoshis ,
10685
+ our_funding_contribution ,
10673
10686
their_funding_contribution_satoshis: None,
10674
10687
funding_tx_locktime: LockTime::from_consensus(locktime),
10675
10688
funding_feerate_sat_per_1000_weight: funding_feerate_per_kw,
@@ -10690,7 +10703,7 @@ where
10690
10703
10691
10704
Ok(msgs::SpliceInit {
10692
10705
channel_id: self.context.channel_id,
10693
- funding_contribution_satoshis: our_funding_contribution_satoshis ,
10706
+ funding_contribution_satoshis: our_funding_contribution.to_sat() ,
10694
10707
funding_feerate_per_kw,
10695
10708
locktime,
10696
10709
funding_pubkey,
@@ -10701,10 +10714,8 @@ where
10701
10714
/// Checks during handling splice_init
10702
10715
#[cfg(splicing)]
10703
10716
pub fn validate_splice_init(
10704
- &self, msg: &msgs::SpliceInit, our_funding_contribution_satoshis: i64 ,
10717
+ &self, msg: &msgs::SpliceInit, our_funding_contribution: SignedAmount ,
10705
10718
) -> Result<FundingScope, ChannelError> {
10706
- let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
10707
-
10708
10719
// TODO(splicing): Add check that we are the quiescence acceptor
10709
10720
10710
10721
// Check if a splice has been initiated already.
@@ -10724,21 +10735,40 @@ where
10724
10735
)));
10725
10736
}
10726
10737
10727
- if their_funding_contribution_satoshis.saturating_add(our_funding_contribution_satoshis) < 0
10728
- {
10738
+ // TODO(splicing): Move this check once user-provided contributions are supported for
10739
+ // counterparty-initiated splices.
10740
+ if our_funding_contribution > SignedAmount::MAX_MONEY {
10741
+ return Err(ChannelError::WarnAndDisconnect(format!(
10742
+ "Channel {} cannot be spliced; our contribution exceeds total bitcoin supply: {}",
10743
+ self.context.channel_id(),
10744
+ our_funding_contribution,
10745
+ )));
10746
+ }
10747
+
10748
+ let their_funding_contribution = SignedAmount::from_sat(msg.funding_contribution_satoshis);
10749
+ if their_funding_contribution > SignedAmount::MAX_MONEY {
10750
+ return Err(ChannelError::WarnAndDisconnect(format!(
10751
+ "Channel {} cannot be spliced; their contribution exceeds total bitcoin supply: {}",
10752
+ self.context.channel_id(),
10753
+ their_funding_contribution,
10754
+ )));
10755
+ }
10756
+
10757
+ debug_assert_eq!(our_funding_contribution, SignedAmount::ZERO);
10758
+ if their_funding_contribution < SignedAmount::ZERO {
10729
10759
return Err(ChannelError::WarnAndDisconnect(format!(
10730
10760
"Splice-out not supported, only splice in, contribution is {} ({} + {})",
10731
- their_funding_contribution_satoshis + our_funding_contribution_satoshis ,
10732
- their_funding_contribution_satoshis ,
10733
- our_funding_contribution_satoshis ,
10761
+ their_funding_contribution + our_funding_contribution ,
10762
+ their_funding_contribution ,
10763
+ our_funding_contribution ,
10734
10764
)));
10735
10765
}
10736
10766
10737
10767
let splice_funding = FundingScope::for_splice(
10738
10768
&self.funding,
10739
10769
&self.context,
10740
- our_funding_contribution_satoshis ,
10741
- their_funding_contribution_satoshis ,
10770
+ our_funding_contribution ,
10771
+ their_funding_contribution ,
10742
10772
msg.funding_pubkey,
10743
10773
)?;
10744
10774
@@ -10763,7 +10793,8 @@ where
10763
10793
ES::Target: EntropySource,
10764
10794
L::Target: Logger,
10765
10795
{
10766
- let splice_funding = self.validate_splice_init(msg, our_funding_contribution_satoshis)?;
10796
+ let our_funding_contribution = SignedAmount::from_sat(our_funding_contribution_satoshis);
10797
+ let splice_funding = self.validate_splice_init(msg, our_funding_contribution)?;
10767
10798
10768
10799
log_info!(
10769
10800
logger,
@@ -10777,7 +10808,7 @@ where
10777
10808
let prev_funding_input = self.funding.to_splice_funding_input();
10778
10809
let funding_negotiation_context = FundingNegotiationContext {
10779
10810
is_initiator: false,
10780
- our_funding_contribution_satoshis ,
10811
+ our_funding_contribution ,
10781
10812
their_funding_contribution_satoshis: Some(their_funding_contribution_satoshis),
10782
10813
funding_tx_locktime: LockTime::from_consensus(msg.locktime),
10783
10814
funding_feerate_sat_per_1000_weight: msg.funding_feerate_per_kw,
@@ -10815,7 +10846,7 @@ where
10815
10846
10816
10847
Ok(msgs::SpliceAck {
10817
10848
channel_id: self.context.channel_id,
10818
- funding_contribution_satoshis: our_funding_contribution_satoshis ,
10849
+ funding_contribution_satoshis: our_funding_contribution.to_sat() ,
10819
10850
funding_pubkey,
10820
10851
require_confirmed_inputs: None,
10821
10852
})
@@ -10862,15 +10893,23 @@ where
10862
10893
},
10863
10894
};
10864
10895
10865
- let our_funding_contribution_satoshis =
10866
- funding_negotiation_context.our_funding_contribution_satoshis;
10867
- let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
10896
+ let our_funding_contribution = funding_negotiation_context.our_funding_contribution;
10897
+ debug_assert!(our_funding_contribution <= SignedAmount::MAX_MONEY);
10898
+
10899
+ let their_funding_contribution = SignedAmount::from_sat(msg.funding_contribution_satoshis);
10900
+ if their_funding_contribution > SignedAmount::MAX_MONEY {
10901
+ return Err(ChannelError::Warn(format!(
10902
+ "Channel {} cannot be spliced; their contribution exceeds total bitcoin supply: {}",
10903
+ self.context.channel_id(),
10904
+ their_funding_contribution,
10905
+ )));
10906
+ }
10868
10907
10869
10908
let splice_funding = FundingScope::for_splice(
10870
10909
&self.funding,
10871
10910
&self.context,
10872
- our_funding_contribution_satoshis ,
10873
- their_funding_contribution_satoshis ,
10911
+ our_funding_contribution ,
10912
+ their_funding_contribution ,
10874
10913
msg.funding_pubkey,
10875
10914
)?;
10876
10915
@@ -12468,7 +12507,7 @@ where
12468
12507
};
12469
12508
let funding_negotiation_context = FundingNegotiationContext {
12470
12509
is_initiator: true,
12471
- our_funding_contribution_satoshis: funding_satoshis as i64,
12510
+ our_funding_contribution: SignedAmount::from_sat( funding_satoshis as i64) ,
12472
12511
// TODO(dual_funding) TODO(splicing) Include counterparty contribution, once that's enabled
12473
12512
their_funding_contribution_satoshis: None,
12474
12513
funding_tx_locktime,
@@ -12578,10 +12617,11 @@ where
12578
12617
L::Target: Logger,
12579
12618
{
12580
12619
// TODO(dual_funding): Take these as input once supported
12581
- let our_funding_satoshis = 0u64;
12620
+ let (our_funding_contribution, our_funding_contribution_sats) = (SignedAmount::ZERO, 0u64) ;
12582
12621
let our_funding_inputs = Vec::new();
12583
12622
12584
- let channel_value_satoshis = our_funding_satoshis.saturating_add(msg.common_fields.funding_satoshis);
12623
+ let channel_value_satoshis =
12624
+ our_funding_contribution_sats.saturating_add(msg.common_fields.funding_satoshis);
12585
12625
let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
12586
12626
channel_value_satoshis, msg.common_fields.dust_limit_satoshis);
12587
12627
let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
@@ -12608,9 +12648,7 @@ where
12608
12648
current_chain_height,
12609
12649
logger,
12610
12650
false,
12611
-
12612
- our_funding_satoshis,
12613
-
12651
+ our_funding_contribution_sats,
12614
12652
counterparty_pubkeys,
12615
12653
channel_type,
12616
12654
holder_selected_channel_reserve_satoshis,
@@ -12625,7 +12663,7 @@ where
12625
12663
12626
12664
let funding_negotiation_context = FundingNegotiationContext {
12627
12665
is_initiator: false,
12628
- our_funding_contribution_satoshis: our_funding_satoshis as i64 ,
12666
+ our_funding_contribution ,
12629
12667
their_funding_contribution_satoshis: Some(msg.common_fields.funding_satoshis as i64),
12630
12668
funding_tx_locktime: LockTime::from_consensus(msg.locktime),
12631
12669
funding_feerate_sat_per_1000_weight: msg.funding_feerate_sat_per_1000_weight,
@@ -12649,7 +12687,7 @@ where
12649
12687
is_initiator: false,
12650
12688
inputs_to_contribute: our_funding_inputs,
12651
12689
shared_funding_input: None,
12652
- shared_funding_output: SharedOwnedOutput::new(shared_funding_output, our_funding_satoshis ),
12690
+ shared_funding_output: SharedOwnedOutput::new(shared_funding_output, our_funding_contribution_sats ),
12653
12691
outputs_to_contribute: Vec::new(),
12654
12692
}
12655
12693
).map_err(|err| {
@@ -12730,7 +12768,7 @@ where
12730
12768
}),
12731
12769
channel_type: Some(self.funding.get_channel_type().clone()),
12732
12770
},
12733
- funding_satoshis: self.funding_negotiation_context.our_funding_contribution_satoshis
12771
+ funding_satoshis: self.funding_negotiation_context.our_funding_contribution.to_sat()
12734
12772
as u64,
12735
12773
second_per_commitment_point,
12736
12774
require_confirmed_inputs: None,
0 commit comments