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};
@@ -2254,20 +2254,22 @@ impl FundingScope {
22542254 /// Constructs a `FundingScope` for splicing a channel.
22552255 #[cfg(splicing)]
22562256 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,
22592259 ) -> Result<Self, ChannelError>
22602260 where
22612261 SP::Target: SignerProvider,
22622262 {
2263+ debug_assert!(our_funding_contribution <= SignedAmount::MAX_MONEY);
2264+
22632265 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() ,
22662268 );
22672269
22682270 let post_value_to_self_msat = AddSigned::checked_add_signed(
22692271 prev_funding.value_to_self_msat,
2270- our_funding_contribution_sats * 1000,
2272+ our_funding_contribution.to_sat() * 1000,
22712273 );
22722274 debug_assert!(post_value_to_self_msat.is_some());
22732275 let post_value_to_self_msat = post_value_to_self_msat.unwrap();
@@ -5965,7 +5967,7 @@ pub(super) struct FundingNegotiationContext {
59655967 /// Whether we initiated the funding negotiation.
59665968 pub is_initiator: bool,
59675969 /// The amount in satoshis we will be contributing to the channel.
5968- pub our_funding_contribution_satoshis: i64 ,
5970+ pub our_funding_contribution: SignedAmount ,
59695971 /// The amount in satoshis our counterparty will be contributing to the channel.
59705972 #[allow(dead_code)] // TODO(dual_funding): Remove once contribution to V2 channels is enabled.
59715973 pub their_funding_contribution_satoshis: Option<i64>,
@@ -6021,7 +6023,7 @@ impl FundingNegotiationContext {
60216023 };
60226024
60236025 // Optionally add change output
6024- if self.our_funding_contribution_satoshis > 0 {
6026+ if self.our_funding_contribution > SignedAmount::ZERO {
60256027 let change_value_opt = calculate_change_output_value(
60266028 &self,
60276029 self.shared_funding_input.is_some(),
@@ -10636,11 +10638,22 @@ where
1063610638
1063710639 // TODO(splicing): check for quiescence
1063810640
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 {
1064010653 return Err(APIError::APIMisuseError {
1064110654 err: format!(
1064210655 "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 ,
1064410657 ),
1064510658 });
1064610659 }
@@ -10653,7 +10666,7 @@ where
1065310666
1065410667 // Check that inputs are sufficient to cover our contribution.
1065510668 let _fee = check_v2_funding_inputs_sufficient(
10656- our_funding_contribution_satoshis ,
10669+ our_funding_contribution.to_sat() ,
1065710670 &our_funding_inputs,
1065810671 true,
1065910672 true,
@@ -10677,7 +10690,7 @@ where
1067710690 let prev_funding_input = self.funding.to_splice_funding_input();
1067810691 let funding_negotiation_context = FundingNegotiationContext {
1067910692 is_initiator: true,
10680- our_funding_contribution_satoshis ,
10693+ our_funding_contribution ,
1068110694 their_funding_contribution_satoshis: None,
1068210695 funding_tx_locktime: LockTime::from_consensus(locktime),
1068310696 funding_feerate_sat_per_1000_weight: funding_feerate_per_kw,
@@ -10698,7 +10711,7 @@ where
1069810711
1069910712 Ok(msgs::SpliceInit {
1070010713 channel_id: self.context.channel_id,
10701- funding_contribution_satoshis: our_funding_contribution_satoshis ,
10714+ funding_contribution_satoshis: our_funding_contribution.to_sat() ,
1070210715 funding_feerate_per_kw,
1070310716 locktime,
1070410717 funding_pubkey,
@@ -10709,10 +10722,8 @@ where
1070910722 /// Checks during handling splice_init
1071010723 #[cfg(splicing)]
1071110724 pub fn validate_splice_init(
10712- &self, msg: &msgs::SpliceInit, our_funding_contribution_satoshis: i64 ,
10725+ &self, msg: &msgs::SpliceInit, our_funding_contribution: SignedAmount ,
1071310726 ) -> Result<FundingScope, ChannelError> {
10714- let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
10715-
1071610727 // TODO(splicing): Add check that we are the quiescence acceptor
1071710728
1071810729 // Check if a splice has been initiated already.
@@ -10732,21 +10743,38 @@ where
1073210743 )));
1073310744 }
1073410745
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 {
1073710765 return Err(ChannelError::WarnAndDisconnect(format!(
1073810766 "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 ,
1074210770 )));
1074310771 }
1074410772
1074510773 let splice_funding = FundingScope::for_splice(
1074610774 &self.funding,
1074710775 &self.context,
10748- our_funding_contribution_satoshis ,
10749- their_funding_contribution_satoshis ,
10776+ our_funding_contribution ,
10777+ their_funding_contribution ,
1075010778 msg.funding_pubkey,
1075110779 )?;
1075210780
@@ -10771,7 +10799,8 @@ where
1077110799 ES::Target: EntropySource,
1077210800 L::Target: Logger,
1077310801 {
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)?;
1077510804
1077610805 log_info!(
1077710806 logger,
@@ -10785,7 +10814,7 @@ where
1078510814 let prev_funding_input = self.funding.to_splice_funding_input();
1078610815 let funding_negotiation_context = FundingNegotiationContext {
1078710816 is_initiator: false,
10788- our_funding_contribution_satoshis ,
10817+ our_funding_contribution ,
1078910818 their_funding_contribution_satoshis: Some(their_funding_contribution_satoshis),
1079010819 funding_tx_locktime: LockTime::from_consensus(msg.locktime),
1079110820 funding_feerate_sat_per_1000_weight: msg.funding_feerate_per_kw,
@@ -10823,7 +10852,7 @@ where
1082310852
1082410853 Ok(msgs::SpliceAck {
1082510854 channel_id: self.context.channel_id,
10826- funding_contribution_satoshis: our_funding_contribution_satoshis ,
10855+ funding_contribution_satoshis: our_funding_contribution.to_sat() ,
1082710856 funding_pubkey,
1082810857 require_confirmed_inputs: None,
1082910858 })
@@ -10870,15 +10899,23 @@ where
1087010899 },
1087110900 };
1087210901
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+ }
1087610913
1087710914 let splice_funding = FundingScope::for_splice(
1087810915 &self.funding,
1087910916 &self.context,
10880- our_funding_contribution_satoshis ,
10881- their_funding_contribution_satoshis ,
10917+ our_funding_contribution ,
10918+ their_funding_contribution ,
1088210919 msg.funding_pubkey,
1088310920 )?;
1088410921
@@ -12476,7 +12513,7 @@ where
1247612513 };
1247712514 let funding_negotiation_context = FundingNegotiationContext {
1247812515 is_initiator: true,
12479- our_funding_contribution_satoshis: funding_satoshis as i64,
12516+ our_funding_contribution: SignedAmount::from_sat( funding_satoshis as i64) ,
1248012517 // TODO(dual_funding) TODO(splicing) Include counterparty contribution, once that's enabled
1248112518 their_funding_contribution_satoshis: None,
1248212519 funding_tx_locktime,
@@ -12586,10 +12623,11 @@ where
1258612623 L::Target: Logger,
1258712624 {
1258812625 // 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) ;
1259012627 let our_funding_inputs = Vec::new();
1259112628
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);
1259312631 let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
1259412632 channel_value_satoshis, msg.common_fields.dust_limit_satoshis);
1259512633 let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
@@ -12616,9 +12654,7 @@ where
1261612654 current_chain_height,
1261712655 logger,
1261812656 false,
12619-
12620- our_funding_satoshis,
12621-
12657+ our_funding_contribution_sats,
1262212658 counterparty_pubkeys,
1262312659 channel_type,
1262412660 holder_selected_channel_reserve_satoshis,
@@ -12633,7 +12669,7 @@ where
1263312669
1263412670 let funding_negotiation_context = FundingNegotiationContext {
1263512671 is_initiator: false,
12636- our_funding_contribution_satoshis: our_funding_satoshis as i64 ,
12672+ our_funding_contribution ,
1263712673 their_funding_contribution_satoshis: Some(msg.common_fields.funding_satoshis as i64),
1263812674 funding_tx_locktime: LockTime::from_consensus(msg.locktime),
1263912675 funding_feerate_sat_per_1000_weight: msg.funding_feerate_sat_per_1000_weight,
@@ -12657,7 +12693,7 @@ where
1265712693 is_initiator: false,
1265812694 inputs_to_contribute: our_funding_inputs,
1265912695 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 ),
1266112697 outputs_to_contribute: Vec::new(),
1266212698 }
1266312699 ).map_err(|err| {
@@ -12738,7 +12774,7 @@ where
1273812774 }),
1273912775 channel_type: Some(self.funding.get_channel_type().clone()),
1274012776 },
12741- funding_satoshis: self.funding_negotiation_context.our_funding_contribution_satoshis
12777+ funding_satoshis: self.funding_negotiation_context.our_funding_contribution.to_sat()
1274212778 as u64,
1274312779 second_per_commitment_point,
1274412780 require_confirmed_inputs: None,
0 commit comments