@@ -11851,6 +11851,26 @@ where
1185111851 self.propose_quiescence(logger, QuiescentAction::Splice { contribution, locktime })
1185211852 }
1185311853
11854+ /// Returns a reference to the funding contribution queued by a pending [`QuiescentAction`],
11855+ /// if any.
11856+ fn queued_funding_contribution(&self) -> Option<&FundingContribution> {
11857+ match &self.quiescent_action {
11858+ Some(QuiescentAction::Splice { contribution, .. }) => Some(contribution),
11859+ _ => None,
11860+ }
11861+ }
11862+
11863+ /// Consumes and returns the funding contribution from the pending [`QuiescentAction`], if any.
11864+ fn take_queued_funding_contribution(&mut self) -> Option<FundingContribution> {
11865+ match &self.quiescent_action {
11866+ Some(QuiescentAction::Splice { .. }) => match self.quiescent_action.take() {
11867+ Some(QuiescentAction::Splice { contribution, .. }) => Some(contribution),
11868+ _ => unreachable!(),
11869+ },
11870+ _ => None,
11871+ }
11872+ }
11873+
1185411874 fn send_splice_init(&mut self, context: FundingNegotiationContext) -> msgs::SpliceInit {
1185511875 debug_assert!(self.pending_splice.is_none());
1185611876 // Rotate the funding pubkey using the prev_funding_txid as a tweak
@@ -11948,10 +11968,6 @@ where
1194811968 ));
1194911969 }
1195011970
11951- // TODO(splicing): Once splice acceptor can contribute, check that inputs are sufficient,
11952- // similarly to the check in `funding_contributed`.
11953- debug_assert_eq!(our_funding_contribution, SignedAmount::ZERO);
11954-
1195511971 let their_funding_contribution = SignedAmount::from_sat(msg.funding_contribution_satoshis);
1195611972 if their_funding_contribution == SignedAmount::ZERO {
1195711973 return Err(ChannelError::WarnAndDisconnect(format!(
@@ -12075,11 +12091,52 @@ where
1207512091 }
1207612092
1207712093 pub(crate) fn splice_init<ES: EntropySource, L: Logger>(
12078- &mut self, msg: &msgs::SpliceInit, our_funding_contribution_satoshis: i64 ,
12079- entropy_source: &ES, holder_node_id: &PublicKey, logger: &L,
12094+ &mut self, msg: &msgs::SpliceInit, entropy_source: &ES, holder_node_id: &PublicKey ,
12095+ logger: &L,
1208012096 ) -> Result<msgs::SpliceAck, ChannelError> {
12081- let our_funding_contribution = SignedAmount::from_sat(our_funding_contribution_satoshis);
12082- let splice_funding = self.validate_splice_init(msg, our_funding_contribution)?;
12097+ let feerate = FeeRate::from_sat_per_kwu(msg.funding_feerate_per_kw as u64);
12098+ let holder_balance = self
12099+ .get_holder_counterparty_balances_floor_incl_fee(&self.funding)
12100+ .map(|(holder, _)| holder)
12101+ .map_err(|e| {
12102+ log_info!(
12103+ logger,
12104+ "Cannot compute holder balance for channel {}: {}; \
12105+ proceeding without contribution",
12106+ self.context.channel_id(),
12107+ e,
12108+ );
12109+ })
12110+ .ok();
12111+ let our_funding_contribution =
12112+ holder_balance.and_then(|_| self.queued_funding_contribution()).and_then(|c| {
12113+ c.net_value_for_acceptor_at_feerate(feerate, holder_balance.unwrap())
12114+ .map_err(|e| {
12115+ log_info!(
12116+ logger,
12117+ "Cannot accommodate initiator's feerate ({}) for channel {}: {}; \
12118+ proceeding without contribution",
12119+ feerate,
12120+ self.context.channel_id(),
12121+ e,
12122+ );
12123+ })
12124+ .ok()
12125+ });
12126+
12127+ let splice_funding =
12128+ self.validate_splice_init(msg, our_funding_contribution.unwrap_or(SignedAmount::ZERO))?;
12129+
12130+ let (our_funding_inputs, our_funding_outputs) = if our_funding_contribution.is_some() {
12131+ self.take_queued_funding_contribution()
12132+ .expect("queued_funding_contribution was Some")
12133+ .for_acceptor_at_feerate(feerate, holder_balance.unwrap())
12134+ .expect("feerate compatibility already checked")
12135+ .into_tx_parts()
12136+ } else {
12137+ Default::default()
12138+ };
12139+ let our_funding_contribution = our_funding_contribution.unwrap_or(SignedAmount::ZERO);
1208312140
1208412141 log_info!(
1208512142 logger,
@@ -12096,8 +12153,8 @@ where
1209612153 funding_tx_locktime: LockTime::from_consensus(msg.locktime),
1209712154 funding_feerate_sat_per_1000_weight: msg.funding_feerate_per_kw,
1209812155 shared_funding_input: Some(prev_funding_input),
12099- our_funding_inputs: Vec::new() ,
12100- our_funding_outputs: Vec::new() ,
12156+ our_funding_inputs,
12157+ our_funding_outputs,
1210112158 };
1210212159
1210312160 let (interactive_tx_constructor, first_message) = funding_negotiation_context
@@ -12109,11 +12166,6 @@ where
1210912166 );
1211012167 debug_assert!(first_message.is_none());
1211112168
12112- // TODO(splicing): if quiescent_action is set, integrate what the user wants to do into the
12113- // counterparty-initiated splice. For always-on nodes this probably isn't a useful
12114- // optimization, but for often-offline nodes it may be, as we may connect and immediately
12115- // go into splicing from both sides.
12116-
1211712169 let new_funding_pubkey = splice_funding.get_holder_pubkeys().funding_pubkey;
1211812170 self.pending_splice = Some(PendingFunding {
1211912171 funding_negotiation: Some(FundingNegotiation::ConstructingTransaction {
0 commit comments