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};
@@ -2254,20 +2254,22 @@ impl FundingScope {
2254
2254
/// Constructs a `FundingScope` for splicing a channel.
2255
2255
#[cfg(splicing)]
2256
2256
fn for_splice<SP: Deref>(
2257
- prev_funding: &Self, context: &ChannelContext<SP>, our_funding_contribution_sats: i64 ,
2258
- their_funding_contribution_sats: i64 , counterparty_funding_pubkey: PublicKey,
2257
+ prev_funding: &Self, context: &ChannelContext<SP>, our_funding_contribution: SignedAmount ,
2258
+ their_funding_contribution: SignedAmount , counterparty_funding_pubkey: PublicKey,
2259
2259
) -> Result<Self, ChannelError>
2260
2260
where
2261
2261
SP::Target: SignerProvider,
2262
2262
{
2263
+ debug_assert!(our_funding_contribution <= SignedAmount::MAX_MONEY);
2264
+
2263
2265
let post_channel_value = prev_funding.compute_post_splice_value(
2264
- our_funding_contribution_sats ,
2265
- their_funding_contribution_sats ,
2266
+ our_funding_contribution.to_sat() ,
2267
+ their_funding_contribution.to_sat() ,
2266
2268
);
2267
2269
2268
2270
let post_value_to_self_msat = AddSigned::checked_add_signed(
2269
2271
prev_funding.value_to_self_msat,
2270
- our_funding_contribution_sats * 1000,
2272
+ our_funding_contribution.to_sat() * 1000,
2271
2273
);
2272
2274
debug_assert!(post_value_to_self_msat.is_some());
2273
2275
let post_value_to_self_msat = post_value_to_self_msat.unwrap();
@@ -5965,7 +5967,7 @@ pub(super) struct FundingNegotiationContext {
5965
5967
/// Whether we initiated the funding negotiation.
5966
5968
pub is_initiator: bool,
5967
5969
/// The amount in satoshis we will be contributing to the channel.
5968
- pub our_funding_contribution_satoshis: i64 ,
5970
+ pub our_funding_contribution: SignedAmount ,
5969
5971
/// The amount in satoshis our counterparty will be contributing to the channel.
5970
5972
#[allow(dead_code)] // TODO(dual_funding): Remove once contribution to V2 channels is enabled.
5971
5973
pub their_funding_contribution_satoshis: Option<i64>,
@@ -6021,7 +6023,7 @@ impl FundingNegotiationContext {
6021
6023
};
6022
6024
6023
6025
// Optionally add change output
6024
- if self.our_funding_contribution_satoshis > 0 {
6026
+ if self.our_funding_contribution > SignedAmount::ZERO {
6025
6027
let change_value_opt = calculate_change_output_value(
6026
6028
&self,
6027
6029
self.shared_funding_input.is_some(),
@@ -10636,11 +10638,22 @@ where
10636
10638
10637
10639
// TODO(splicing): check for quiescence
10638
10640
10639
- if our_funding_contribution_satoshis < 0 {
10641
+ let our_funding_contribution = SignedAmount::from_sat(our_funding_contribution_satoshis);
10642
+ if our_funding_contribution > SignedAmount::MAX_MONEY {
10643
+ return Err(APIError::APIMisuseError {
10644
+ err: format!(
10645
+ "Channel {} cannot be spliced; contribution exceeds total bitcoin supply: {}",
10646
+ self.context.channel_id(),
10647
+ our_funding_contribution,
10648
+ ),
10649
+ });
10650
+ }
10651
+
10652
+ if our_funding_contribution < SignedAmount::ZERO {
10640
10653
return Err(APIError::APIMisuseError {
10641
10654
err: format!(
10642
10655
"TODO(splicing): Splice-out not supported, only splice in; channel ID {}, contribution {}",
10643
- self.context.channel_id(), our_funding_contribution_satoshis ,
10656
+ self.context.channel_id(), our_funding_contribution ,
10644
10657
),
10645
10658
});
10646
10659
}
@@ -10653,7 +10666,7 @@ where
10653
10666
10654
10667
// Check that inputs are sufficient to cover our contribution.
10655
10668
let _fee = check_v2_funding_inputs_sufficient(
10656
- our_funding_contribution_satoshis ,
10669
+ our_funding_contribution.to_sat() ,
10657
10670
&our_funding_inputs,
10658
10671
true,
10659
10672
true,
@@ -10677,7 +10690,7 @@ where
10677
10690
let prev_funding_input = self.funding.to_splice_funding_input();
10678
10691
let funding_negotiation_context = FundingNegotiationContext {
10679
10692
is_initiator: true,
10680
- our_funding_contribution_satoshis ,
10693
+ our_funding_contribution ,
10681
10694
their_funding_contribution_satoshis: None,
10682
10695
funding_tx_locktime: LockTime::from_consensus(locktime),
10683
10696
funding_feerate_sat_per_1000_weight: funding_feerate_per_kw,
@@ -10698,7 +10711,7 @@ where
10698
10711
10699
10712
Ok(msgs::SpliceInit {
10700
10713
channel_id: self.context.channel_id,
10701
- funding_contribution_satoshis: our_funding_contribution_satoshis ,
10714
+ funding_contribution_satoshis: our_funding_contribution.to_sat() ,
10702
10715
funding_feerate_per_kw,
10703
10716
locktime,
10704
10717
funding_pubkey,
@@ -10709,10 +10722,8 @@ where
10709
10722
/// Checks during handling splice_init
10710
10723
#[cfg(splicing)]
10711
10724
pub fn validate_splice_init(
10712
- &self, msg: &msgs::SpliceInit, our_funding_contribution_satoshis: i64 ,
10725
+ &self, msg: &msgs::SpliceInit, our_funding_contribution: SignedAmount ,
10713
10726
) -> Result<FundingScope, ChannelError> {
10714
- let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
10715
-
10716
10727
// TODO(splicing): Add check that we are the quiescence acceptor
10717
10728
10718
10729
// Check if a splice has been initiated already.
@@ -10732,21 +10743,38 @@ where
10732
10743
)));
10733
10744
}
10734
10745
10735
- if their_funding_contribution_satoshis.saturating_add(our_funding_contribution_satoshis) < 0
10736
- {
10746
+ if our_funding_contribution > SignedAmount::MAX_MONEY {
10747
+ return Err(ChannelError::WarnAndDisconnect(format!(
10748
+ "Channel {} cannot be spliced; our contribution exceeds total bitcoin supply: {}",
10749
+ self.context.channel_id(),
10750
+ our_funding_contribution,
10751
+ )));
10752
+ }
10753
+
10754
+ let their_funding_contribution = SignedAmount::from_sat(msg.funding_contribution_satoshis);
10755
+ if their_funding_contribution > SignedAmount::MAX_MONEY {
10756
+ return Err(ChannelError::WarnAndDisconnect(format!(
10757
+ "Channel {} cannot be spliced; their contribution exceeds total bitcoin supply: {}",
10758
+ self.context.channel_id(),
10759
+ their_funding_contribution,
10760
+ )));
10761
+ }
10762
+
10763
+ debug_assert_eq!(our_funding_contribution, SignedAmount::ZERO);
10764
+ if their_funding_contribution < SignedAmount::ZERO {
10737
10765
return Err(ChannelError::WarnAndDisconnect(format!(
10738
10766
"Splice-out not supported, only splice in, contribution is {} ({} + {})",
10739
- their_funding_contribution_satoshis + our_funding_contribution_satoshis ,
10740
- their_funding_contribution_satoshis ,
10741
- our_funding_contribution_satoshis ,
10767
+ their_funding_contribution + our_funding_contribution ,
10768
+ their_funding_contribution ,
10769
+ our_funding_contribution ,
10742
10770
)));
10743
10771
}
10744
10772
10745
10773
let splice_funding = FundingScope::for_splice(
10746
10774
&self.funding,
10747
10775
&self.context,
10748
- our_funding_contribution_satoshis ,
10749
- their_funding_contribution_satoshis ,
10776
+ our_funding_contribution ,
10777
+ their_funding_contribution ,
10750
10778
msg.funding_pubkey,
10751
10779
)?;
10752
10780
@@ -10771,7 +10799,8 @@ where
10771
10799
ES::Target: EntropySource,
10772
10800
L::Target: Logger,
10773
10801
{
10774
- let splice_funding = self.validate_splice_init(msg, our_funding_contribution_satoshis)?;
10802
+ let our_funding_contribution = SignedAmount::from_sat(our_funding_contribution_satoshis);
10803
+ let splice_funding = self.validate_splice_init(msg, our_funding_contribution)?;
10775
10804
10776
10805
log_info!(
10777
10806
logger,
@@ -10785,7 +10814,7 @@ where
10785
10814
let prev_funding_input = self.funding.to_splice_funding_input();
10786
10815
let funding_negotiation_context = FundingNegotiationContext {
10787
10816
is_initiator: false,
10788
- our_funding_contribution_satoshis ,
10817
+ our_funding_contribution ,
10789
10818
their_funding_contribution_satoshis: Some(their_funding_contribution_satoshis),
10790
10819
funding_tx_locktime: LockTime::from_consensus(msg.locktime),
10791
10820
funding_feerate_sat_per_1000_weight: msg.funding_feerate_per_kw,
@@ -10823,7 +10852,7 @@ where
10823
10852
10824
10853
Ok(msgs::SpliceAck {
10825
10854
channel_id: self.context.channel_id,
10826
- funding_contribution_satoshis: our_funding_contribution_satoshis ,
10855
+ funding_contribution_satoshis: our_funding_contribution.to_sat() ,
10827
10856
funding_pubkey,
10828
10857
require_confirmed_inputs: None,
10829
10858
})
@@ -10870,15 +10899,23 @@ where
10870
10899
},
10871
10900
};
10872
10901
10873
- let our_funding_contribution_satoshis =
10874
- funding_negotiation_context.our_funding_contribution_satoshis;
10875
- let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
10902
+ let our_funding_contribution = funding_negotiation_context.our_funding_contribution;
10903
+ debug_assert!(our_funding_contribution <= SignedAmount::MAX_MONEY);
10904
+
10905
+ let their_funding_contribution = SignedAmount::from_sat(msg.funding_contribution_satoshis);
10906
+ if their_funding_contribution > SignedAmount::MAX_MONEY {
10907
+ return Err(ChannelError::Warn(format!(
10908
+ "Channel {} cannot be spliced; their contribution exceeds total bitcoin supply: {}",
10909
+ self.context.channel_id(),
10910
+ their_funding_contribution,
10911
+ )));
10912
+ }
10876
10913
10877
10914
let splice_funding = FundingScope::for_splice(
10878
10915
&self.funding,
10879
10916
&self.context,
10880
- our_funding_contribution_satoshis ,
10881
- their_funding_contribution_satoshis ,
10917
+ our_funding_contribution ,
10918
+ their_funding_contribution ,
10882
10919
msg.funding_pubkey,
10883
10920
)?;
10884
10921
@@ -12476,7 +12513,7 @@ where
12476
12513
};
12477
12514
let funding_negotiation_context = FundingNegotiationContext {
12478
12515
is_initiator: true,
12479
- our_funding_contribution_satoshis: funding_satoshis as i64,
12516
+ our_funding_contribution: SignedAmount::from_sat( funding_satoshis as i64) ,
12480
12517
// TODO(dual_funding) TODO(splicing) Include counterparty contribution, once that's enabled
12481
12518
their_funding_contribution_satoshis: None,
12482
12519
funding_tx_locktime,
@@ -12586,10 +12623,11 @@ where
12586
12623
L::Target: Logger,
12587
12624
{
12588
12625
// TODO(dual_funding): Take these as input once supported
12589
- let our_funding_satoshis = 0u64;
12626
+ let (our_funding_contribution, our_funding_contribution_sats) = (SignedAmount::ZERO, 0u64) ;
12590
12627
let our_funding_inputs = Vec::new();
12591
12628
12592
- let channel_value_satoshis = our_funding_satoshis.saturating_add(msg.common_fields.funding_satoshis);
12629
+ let channel_value_satoshis =
12630
+ our_funding_contribution_sats.saturating_add(msg.common_fields.funding_satoshis);
12593
12631
let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
12594
12632
channel_value_satoshis, msg.common_fields.dust_limit_satoshis);
12595
12633
let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
@@ -12616,9 +12654,7 @@ where
12616
12654
current_chain_height,
12617
12655
logger,
12618
12656
false,
12619
-
12620
- our_funding_satoshis,
12621
-
12657
+ our_funding_contribution_sats,
12622
12658
counterparty_pubkeys,
12623
12659
channel_type,
12624
12660
holder_selected_channel_reserve_satoshis,
@@ -12633,7 +12669,7 @@ where
12633
12669
12634
12670
let funding_negotiation_context = FundingNegotiationContext {
12635
12671
is_initiator: false,
12636
- our_funding_contribution_satoshis: our_funding_satoshis as i64 ,
12672
+ our_funding_contribution ,
12637
12673
their_funding_contribution_satoshis: Some(msg.common_fields.funding_satoshis as i64),
12638
12674
funding_tx_locktime: LockTime::from_consensus(msg.locktime),
12639
12675
funding_feerate_sat_per_1000_weight: msg.funding_feerate_sat_per_1000_weight,
@@ -12657,7 +12693,7 @@ where
12657
12693
is_initiator: false,
12658
12694
inputs_to_contribute: our_funding_inputs,
12659
12695
shared_funding_input: None,
12660
- shared_funding_output: SharedOwnedOutput::new(shared_funding_output, our_funding_satoshis ),
12696
+ shared_funding_output: SharedOwnedOutput::new(shared_funding_output, our_funding_contribution_sats ),
12661
12697
outputs_to_contribute: Vec::new(),
12662
12698
}
12663
12699
).map_err(|err| {
@@ -12738,7 +12774,7 @@ where
12738
12774
}),
12739
12775
channel_type: Some(self.funding.get_channel_type().clone()),
12740
12776
},
12741
- funding_satoshis: self.funding_negotiation_context.our_funding_contribution_satoshis
12777
+ funding_satoshis: self.funding_negotiation_context.our_funding_contribution.to_sat()
12742
12778
as u64,
12743
12779
second_per_commitment_point,
12744
12780
require_confirmed_inputs: None,
0 commit comments