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,38 @@ where
10724
10735
)));
10725
10736
}
10726
10737
10727
- if their_funding_contribution_satoshis.saturating_add(our_funding_contribution_satoshis) < 0
10728
- {
10738
+ if our_funding_contribution > SignedAmount::MAX_MONEY {
10739
+ return Err(ChannelError::WarnAndDisconnect(format!(
10740
+ "Channel {} cannot be spliced; our contribution exceeds total bitcoin supply: {}",
10741
+ self.context.channel_id(),
10742
+ our_funding_contribution,
10743
+ )));
10744
+ }
10745
+
10746
+ let their_funding_contribution = SignedAmount::from_sat(msg.funding_contribution_satoshis);
10747
+ if their_funding_contribution > SignedAmount::MAX_MONEY {
10748
+ return Err(ChannelError::WarnAndDisconnect(format!(
10749
+ "Channel {} cannot be spliced; their contribution exceeds total bitcoin supply: {}",
10750
+ self.context.channel_id(),
10751
+ their_funding_contribution,
10752
+ )));
10753
+ }
10754
+
10755
+ debug_assert_eq!(our_funding_contribution, SignedAmount::ZERO);
10756
+ if their_funding_contribution < SignedAmount::ZERO {
10729
10757
return Err(ChannelError::WarnAndDisconnect(format!(
10730
10758
"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 ,
10759
+ their_funding_contribution + our_funding_contribution ,
10760
+ their_funding_contribution ,
10761
+ our_funding_contribution ,
10734
10762
)));
10735
10763
}
10736
10764
10737
10765
let splice_funding = FundingScope::for_splice(
10738
10766
&self.funding,
10739
10767
&self.context,
10740
- our_funding_contribution_satoshis ,
10741
- their_funding_contribution_satoshis ,
10768
+ our_funding_contribution ,
10769
+ their_funding_contribution ,
10742
10770
msg.funding_pubkey,
10743
10771
)?;
10744
10772
@@ -10763,7 +10791,8 @@ where
10763
10791
ES::Target: EntropySource,
10764
10792
L::Target: Logger,
10765
10793
{
10766
- let splice_funding = self.validate_splice_init(msg, our_funding_contribution_satoshis)?;
10794
+ let our_funding_contribution = SignedAmount::from_sat(our_funding_contribution_satoshis);
10795
+ let splice_funding = self.validate_splice_init(msg, our_funding_contribution)?;
10767
10796
10768
10797
log_info!(
10769
10798
logger,
@@ -10777,7 +10806,7 @@ where
10777
10806
let prev_funding_input = self.funding.to_splice_funding_input();
10778
10807
let funding_negotiation_context = FundingNegotiationContext {
10779
10808
is_initiator: false,
10780
- our_funding_contribution_satoshis ,
10809
+ our_funding_contribution ,
10781
10810
their_funding_contribution_satoshis: Some(their_funding_contribution_satoshis),
10782
10811
funding_tx_locktime: LockTime::from_consensus(msg.locktime),
10783
10812
funding_feerate_sat_per_1000_weight: msg.funding_feerate_per_kw,
@@ -10815,7 +10844,7 @@ where
10815
10844
10816
10845
Ok(msgs::SpliceAck {
10817
10846
channel_id: self.context.channel_id,
10818
- funding_contribution_satoshis: our_funding_contribution_satoshis ,
10847
+ funding_contribution_satoshis: our_funding_contribution.to_sat() ,
10819
10848
funding_pubkey,
10820
10849
require_confirmed_inputs: None,
10821
10850
})
@@ -10862,15 +10891,23 @@ where
10862
10891
},
10863
10892
};
10864
10893
10865
- let our_funding_contribution_satoshis =
10866
- funding_negotiation_context.our_funding_contribution_satoshis;
10867
- let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
10894
+ let our_funding_contribution = funding_negotiation_context.our_funding_contribution;
10895
+ debug_assert!(our_funding_contribution <= SignedAmount::MAX_MONEY);
10896
+
10897
+ let their_funding_contribution = SignedAmount::from_sat(msg.funding_contribution_satoshis);
10898
+ if their_funding_contribution > SignedAmount::MAX_MONEY {
10899
+ return Err(ChannelError::Warn(format!(
10900
+ "Channel {} cannot be spliced; their contribution exceeds total bitcoin supply: {}",
10901
+ self.context.channel_id(),
10902
+ their_funding_contribution,
10903
+ )));
10904
+ }
10868
10905
10869
10906
let splice_funding = FundingScope::for_splice(
10870
10907
&self.funding,
10871
10908
&self.context,
10872
- our_funding_contribution_satoshis ,
10873
- their_funding_contribution_satoshis ,
10909
+ our_funding_contribution ,
10910
+ their_funding_contribution ,
10874
10911
msg.funding_pubkey,
10875
10912
)?;
10876
10913
@@ -12468,7 +12505,7 @@ where
12468
12505
};
12469
12506
let funding_negotiation_context = FundingNegotiationContext {
12470
12507
is_initiator: true,
12471
- our_funding_contribution_satoshis: funding_satoshis as i64,
12508
+ our_funding_contribution: SignedAmount::from_sat( funding_satoshis as i64) ,
12472
12509
// TODO(dual_funding) TODO(splicing) Include counterparty contribution, once that's enabled
12473
12510
their_funding_contribution_satoshis: None,
12474
12511
funding_tx_locktime,
@@ -12578,10 +12615,11 @@ where
12578
12615
L::Target: Logger,
12579
12616
{
12580
12617
// TODO(dual_funding): Take these as input once supported
12581
- let our_funding_satoshis = 0u64;
12618
+ let (our_funding_contribution, our_funding_contribution_sats) = (SignedAmount::ZERO, 0u64) ;
12582
12619
let our_funding_inputs = Vec::new();
12583
12620
12584
- let channel_value_satoshis = our_funding_satoshis.saturating_add(msg.common_fields.funding_satoshis);
12621
+ let channel_value_satoshis =
12622
+ our_funding_contribution_sats.saturating_add(msg.common_fields.funding_satoshis);
12585
12623
let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
12586
12624
channel_value_satoshis, msg.common_fields.dust_limit_satoshis);
12587
12625
let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
@@ -12608,9 +12646,7 @@ where
12608
12646
current_chain_height,
12609
12647
logger,
12610
12648
false,
12611
-
12612
- our_funding_satoshis,
12613
-
12649
+ our_funding_contribution_sats,
12614
12650
counterparty_pubkeys,
12615
12651
channel_type,
12616
12652
holder_selected_channel_reserve_satoshis,
@@ -12625,7 +12661,7 @@ where
12625
12661
12626
12662
let funding_negotiation_context = FundingNegotiationContext {
12627
12663
is_initiator: false,
12628
- our_funding_contribution_satoshis: our_funding_satoshis as i64 ,
12664
+ our_funding_contribution ,
12629
12665
their_funding_contribution_satoshis: Some(msg.common_fields.funding_satoshis as i64),
12630
12666
funding_tx_locktime: LockTime::from_consensus(msg.locktime),
12631
12667
funding_feerate_sat_per_1000_weight: msg.funding_feerate_sat_per_1000_weight,
@@ -12649,7 +12685,7 @@ where
12649
12685
is_initiator: false,
12650
12686
inputs_to_contribute: our_funding_inputs,
12651
12687
shared_funding_input: None,
12652
- shared_funding_output: SharedOwnedOutput::new(shared_funding_output, our_funding_satoshis ),
12688
+ shared_funding_output: SharedOwnedOutput::new(shared_funding_output, our_funding_contribution_sats ),
12653
12689
outputs_to_contribute: Vec::new(),
12654
12690
}
12655
12691
).map_err(|err| {
@@ -12730,7 +12766,7 @@ where
12730
12766
}),
12731
12767
channel_type: Some(self.funding.get_channel_type().clone()),
12732
12768
},
12733
- funding_satoshis: self.funding_negotiation_context.our_funding_contribution_satoshis
12769
+ funding_satoshis: self.funding_negotiation_context.our_funding_contribution.to_sat()
12734
12770
as u64,
12735
12771
second_per_commitment_point,
12736
12772
require_confirmed_inputs: None,
0 commit comments