88// licenses.
99
1010use bitcoin::absolute::LockTime;
11- use bitcoin::amount::Amount;
11+ use bitcoin::amount::{ Amount, SignedAmount} ;
1212use bitcoin::consensus::encode;
1313use bitcoin::constants::ChainHash;
1414use bitcoin::script::{Builder, Script, ScriptBuf, WScriptHash};
@@ -2244,20 +2244,23 @@ impl FundingScope {
22442244 /// Constructs a `FundingScope` for splicing a channel.
22452245 #[cfg(splicing)]
22462246 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,
22492249 ) -> Result<Self, ChannelError>
22502250 where
22512251 SP::Target: SignerProvider,
22522252 {
2253+ debug_assert!(our_funding_contribution.abs() <= SignedAmount::MAX_MONEY);
2254+ debug_assert!(their_funding_contribution.abs() <= SignedAmount::MAX_MONEY);
2255+
22532256 let post_channel_value = prev_funding.compute_post_splice_value(
2254- our_funding_contribution_sats ,
2255- their_funding_contribution_sats ,
2257+ our_funding_contribution.to_sat() ,
2258+ their_funding_contribution.to_sat() ,
22562259 );
22572260
22582261 let post_value_to_self_msat = AddSigned::checked_add_signed(
22592262 prev_funding.value_to_self_msat,
2260- our_funding_contribution_sats * 1000,
2263+ our_funding_contribution.to_sat() * 1000,
22612264 );
22622265 debug_assert!(post_value_to_self_msat.is_some());
22632266 let post_value_to_self_msat = post_value_to_self_msat.unwrap();
@@ -5964,7 +5967,7 @@ pub(super) struct FundingNegotiationContext {
59645967 /// Whether we initiated the funding negotiation.
59655968 pub is_initiator: bool,
59665969 /// The amount in satoshis we will be contributing to the channel.
5967- pub our_funding_contribution_satoshis: i64 ,
5970+ pub our_funding_contribution: SignedAmount ,
59685971 /// The amount in satoshis our counterparty will be contributing to the channel.
59695972 #[allow(dead_code)] // TODO(dual_funding): Remove once contribution to V2 channels is enabled.
59705973 pub their_funding_contribution_satoshis: Option<i64>,
@@ -6020,7 +6023,7 @@ impl FundingNegotiationContext {
60206023 };
60216024
60226025 // Optionally add change output
6023- if self.our_funding_contribution_satoshis > 0 {
6026+ if self.our_funding_contribution > SignedAmount::ZERO {
60246027 let change_value_opt = calculate_change_output_value(
60256028 &self,
60266029 self.shared_funding_input.is_some(),
@@ -10628,11 +10631,22 @@ where
1062810631
1062910632 // TODO(splicing): check for quiescence
1063010633
10631- if our_funding_contribution_satoshis < 0 {
10634+ let our_funding_contribution = SignedAmount::from_sat(our_funding_contribution_satoshis);
10635+ if our_funding_contribution > SignedAmount::MAX_MONEY {
10636+ return Err(APIError::APIMisuseError {
10637+ err: format!(
10638+ "Channel {} cannot be spliced; contribution exceeds total bitcoin supply: {}",
10639+ self.context.channel_id(),
10640+ our_funding_contribution,
10641+ ),
10642+ });
10643+ }
10644+
10645+ if our_funding_contribution < SignedAmount::ZERO {
1063210646 return Err(APIError::APIMisuseError {
1063310647 err: format!(
1063410648 "TODO(splicing): Splice-out not supported, only splice in; channel ID {}, contribution {}",
10635- self.context.channel_id(), our_funding_contribution_satoshis ,
10649+ self.context.channel_id(), our_funding_contribution ,
1063610650 ),
1063710651 });
1063810652 }
@@ -10645,7 +10659,7 @@ where
1064510659
1064610660 // Check that inputs are sufficient to cover our contribution.
1064710661 let _fee = check_v2_funding_inputs_sufficient(
10648- our_funding_contribution_satoshis ,
10662+ our_funding_contribution.to_sat() ,
1064910663 &our_funding_inputs,
1065010664 true,
1065110665 true,
@@ -10669,7 +10683,7 @@ where
1066910683 let prev_funding_input = self.funding.to_splice_funding_input();
1067010684 let funding_negotiation_context = FundingNegotiationContext {
1067110685 is_initiator: true,
10672- our_funding_contribution_satoshis ,
10686+ our_funding_contribution ,
1067310687 their_funding_contribution_satoshis: None,
1067410688 funding_tx_locktime: LockTime::from_consensus(locktime),
1067510689 funding_feerate_sat_per_1000_weight: funding_feerate_per_kw,
@@ -10690,7 +10704,7 @@ where
1069010704
1069110705 Ok(msgs::SpliceInit {
1069210706 channel_id: self.context.channel_id,
10693- funding_contribution_satoshis: our_funding_contribution_satoshis ,
10707+ funding_contribution_satoshis: our_funding_contribution.to_sat() ,
1069410708 funding_feerate_per_kw,
1069510709 locktime,
1069610710 funding_pubkey,
@@ -10701,10 +10715,8 @@ where
1070110715 /// Checks during handling splice_init
1070210716 #[cfg(splicing)]
1070310717 pub fn validate_splice_init(
10704- &self, msg: &msgs::SpliceInit, our_funding_contribution_satoshis: i64 ,
10718+ &self, msg: &msgs::SpliceInit, our_funding_contribution: SignedAmount ,
1070510719 ) -> Result<FundingScope, ChannelError> {
10706- let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
10707-
1070810720 // TODO(splicing): Add check that we are the quiescence acceptor
1070910721
1071010722 // Check if a splice has been initiated already.
@@ -10724,21 +10736,40 @@ where
1072410736 )));
1072510737 }
1072610738
10727- if their_funding_contribution_satoshis.saturating_add(our_funding_contribution_satoshis) < 0
10728- {
10739+ // TODO(splicing): Move this check once user-provided contributions are supported for
10740+ // counterparty-initiated splices.
10741+ if our_funding_contribution > SignedAmount::MAX_MONEY {
10742+ return Err(ChannelError::WarnAndDisconnect(format!(
10743+ "Channel {} cannot be spliced; our contribution exceeds total bitcoin supply: {}",
10744+ self.context.channel_id(),
10745+ our_funding_contribution,
10746+ )));
10747+ }
10748+
10749+ let their_funding_contribution = SignedAmount::from_sat(msg.funding_contribution_satoshis);
10750+ if their_funding_contribution > SignedAmount::MAX_MONEY {
10751+ return Err(ChannelError::WarnAndDisconnect(format!(
10752+ "Channel {} cannot be spliced; their contribution exceeds total bitcoin supply: {}",
10753+ self.context.channel_id(),
10754+ their_funding_contribution,
10755+ )));
10756+ }
10757+
10758+ debug_assert_eq!(our_funding_contribution, SignedAmount::ZERO);
10759+ if their_funding_contribution < SignedAmount::ZERO {
1072910760 return Err(ChannelError::WarnAndDisconnect(format!(
1073010761 "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 ,
10762+ their_funding_contribution + our_funding_contribution ,
10763+ their_funding_contribution ,
10764+ our_funding_contribution ,
1073410765 )));
1073510766 }
1073610767
1073710768 let splice_funding = FundingScope::for_splice(
1073810769 &self.funding,
1073910770 &self.context,
10740- our_funding_contribution_satoshis ,
10741- their_funding_contribution_satoshis ,
10771+ our_funding_contribution ,
10772+ their_funding_contribution ,
1074210773 msg.funding_pubkey,
1074310774 )?;
1074410775
@@ -10763,7 +10794,8 @@ where
1076310794 ES::Target: EntropySource,
1076410795 L::Target: Logger,
1076510796 {
10766- let splice_funding = self.validate_splice_init(msg, our_funding_contribution_satoshis)?;
10797+ let our_funding_contribution = SignedAmount::from_sat(our_funding_contribution_satoshis);
10798+ let splice_funding = self.validate_splice_init(msg, our_funding_contribution)?;
1076710799
1076810800 log_info!(
1076910801 logger,
@@ -10777,7 +10809,7 @@ where
1077710809 let prev_funding_input = self.funding.to_splice_funding_input();
1077810810 let funding_negotiation_context = FundingNegotiationContext {
1077910811 is_initiator: false,
10780- our_funding_contribution_satoshis ,
10812+ our_funding_contribution ,
1078110813 their_funding_contribution_satoshis: Some(their_funding_contribution_satoshis),
1078210814 funding_tx_locktime: LockTime::from_consensus(msg.locktime),
1078310815 funding_feerate_sat_per_1000_weight: msg.funding_feerate_per_kw,
@@ -10815,7 +10847,7 @@ where
1081510847
1081610848 Ok(msgs::SpliceAck {
1081710849 channel_id: self.context.channel_id,
10818- funding_contribution_satoshis: our_funding_contribution_satoshis ,
10850+ funding_contribution_satoshis: our_funding_contribution.to_sat() ,
1081910851 funding_pubkey,
1082010852 require_confirmed_inputs: None,
1082110853 })
@@ -10862,15 +10894,23 @@ where
1086210894 },
1086310895 };
1086410896
10865- let our_funding_contribution_satoshis =
10866- funding_negotiation_context.our_funding_contribution_satoshis;
10867- let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
10897+ let our_funding_contribution = funding_negotiation_context.our_funding_contribution;
10898+ debug_assert!(our_funding_contribution <= SignedAmount::MAX_MONEY);
10899+
10900+ let their_funding_contribution = SignedAmount::from_sat(msg.funding_contribution_satoshis);
10901+ if their_funding_contribution > SignedAmount::MAX_MONEY {
10902+ return Err(ChannelError::Warn(format!(
10903+ "Channel {} cannot be spliced; their contribution exceeds total bitcoin supply: {}",
10904+ self.context.channel_id(),
10905+ their_funding_contribution,
10906+ )));
10907+ }
1086810908
1086910909 let splice_funding = FundingScope::for_splice(
1087010910 &self.funding,
1087110911 &self.context,
10872- our_funding_contribution_satoshis ,
10873- their_funding_contribution_satoshis ,
10912+ our_funding_contribution ,
10913+ their_funding_contribution ,
1087410914 msg.funding_pubkey,
1087510915 )?;
1087610916
@@ -12468,7 +12508,7 @@ where
1246812508 };
1246912509 let funding_negotiation_context = FundingNegotiationContext {
1247012510 is_initiator: true,
12471- our_funding_contribution_satoshis: funding_satoshis as i64,
12511+ our_funding_contribution: SignedAmount::from_sat( funding_satoshis as i64) ,
1247212512 // TODO(dual_funding) TODO(splicing) Include counterparty contribution, once that's enabled
1247312513 their_funding_contribution_satoshis: None,
1247412514 funding_tx_locktime,
@@ -12578,10 +12618,11 @@ where
1257812618 L::Target: Logger,
1257912619 {
1258012620 // TODO(dual_funding): Take these as input once supported
12581- let our_funding_satoshis = 0u64;
12621+ let (our_funding_contribution, our_funding_contribution_sats) = (SignedAmount::ZERO, 0u64) ;
1258212622 let our_funding_inputs = Vec::new();
1258312623
12584- let channel_value_satoshis = our_funding_satoshis.saturating_add(msg.common_fields.funding_satoshis);
12624+ let channel_value_satoshis =
12625+ our_funding_contribution_sats.saturating_add(msg.common_fields.funding_satoshis);
1258512626 let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
1258612627 channel_value_satoshis, msg.common_fields.dust_limit_satoshis);
1258712628 let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
@@ -12608,9 +12649,7 @@ where
1260812649 current_chain_height,
1260912650 logger,
1261012651 false,
12611-
12612- our_funding_satoshis,
12613-
12652+ our_funding_contribution_sats,
1261412653 counterparty_pubkeys,
1261512654 channel_type,
1261612655 holder_selected_channel_reserve_satoshis,
@@ -12625,7 +12664,7 @@ where
1262512664
1262612665 let funding_negotiation_context = FundingNegotiationContext {
1262712666 is_initiator: false,
12628- our_funding_contribution_satoshis: our_funding_satoshis as i64 ,
12667+ our_funding_contribution ,
1262912668 their_funding_contribution_satoshis: Some(msg.common_fields.funding_satoshis as i64),
1263012669 funding_tx_locktime: LockTime::from_consensus(msg.locktime),
1263112670 funding_feerate_sat_per_1000_weight: msg.funding_feerate_sat_per_1000_weight,
@@ -12649,7 +12688,7 @@ where
1264912688 is_initiator: false,
1265012689 inputs_to_contribute: our_funding_inputs,
1265112690 shared_funding_input: None,
12652- shared_funding_output: SharedOwnedOutput::new(shared_funding_output, our_funding_satoshis ),
12691+ shared_funding_output: SharedOwnedOutput::new(shared_funding_output, our_funding_contribution_sats ),
1265312692 outputs_to_contribute: Vec::new(),
1265412693 }
1265512694 ).map_err(|err| {
@@ -12730,7 +12769,7 @@ where
1273012769 }),
1273112770 channel_type: Some(self.funding.get_channel_type().clone()),
1273212771 },
12733- funding_satoshis: self.funding_negotiation_context.our_funding_contribution_satoshis
12772+ funding_satoshis: self.funding_negotiation_context.our_funding_contribution.to_sat()
1273412773 as u64,
1273512774 second_per_commitment_point,
1273612775 require_confirmed_inputs: None,
0 commit comments