@@ -1864,6 +1864,7 @@ impl FundingScope {
18641864#[cfg(splicing)]
18651865struct PendingSplice {
18661866 pub our_funding_contribution: i64,
1867+ confirmed_funding_txid: Option<Txid>,
18671868}
18681869
18691870/// Contains everything about the channel including state, and various flags.
@@ -4967,6 +4968,13 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
49674968 _ => todo!()
49684969 }
49694970 }
4971+
4972+ #[cfg(splicing)]
4973+ fn check_get_splice_locked<L: Deref>(&mut self, funding: &FundingScope, height: u32, logger: &L) -> Option<msgs::SpliceLocked>
4974+ where L::Target: Logger
4975+ {
4976+ None
4977+ }
49704978}
49714979
49724980// Internal utility functions for channels
@@ -8287,20 +8295,29 @@ impl<SP: Deref> FundedChannel<SP> where
82878295 L::Target: Logger
82888296 {
82898297 struct ConfirmedFunding<'a> {
8298+ funding: &'a mut FundingScope,
82908299 funding_tx: &'a Transaction,
82918300 }
82928301
82938302 let mut confirmed_funding = None;
8294- if let Some(funding_txo) = self.funding.get_funding_txo() {
8303+ let mut confirmed_funding_tx = None;
8304+ let current_funding_txo = self.funding.get_funding_txo();
8305+ let funding_iter = core::iter::once(&mut self.funding).chain(self.pending_funding.iter_mut());
8306+ for (funding, funding_txo) in funding_iter.filter_map(|funding| funding.get_funding_txo().map(|txo| (funding, txo))) {
82958307 for &(index_in_block, tx) in txdata.iter() {
82968308 // Check if the transaction is the expected funding transaction, and if it is,
82978309 // check that it pays the right amount to the right script.
8298- if self. funding.funding_tx_confirmation_height == 0 {
8310+ if funding.funding_tx_confirmation_height == 0 {
82998311 if tx.compute_txid() == funding_txo.txid {
8312+ if confirmed_funding_tx.is_some() {
8313+ let err_reason = "funding tx of another pending funding already confirmed";
8314+ return Err(ClosureReason::ProcessingError { err: err_reason.to_owned() });
8315+ }
8316+
83008317 let txo_idx = funding_txo.index as usize;
8301- if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self. funding.get_funding_redeemscript().to_p2wsh() ||
8302- tx.output[txo_idx].value.to_sat() != self. funding.get_value_satoshis() {
8303- if self. funding.is_outbound() {
8318+ if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != funding.get_funding_redeemscript().to_p2wsh() ||
8319+ tx.output[txo_idx].value.to_sat() != funding.get_value_satoshis() {
8320+ if funding.is_outbound() {
83048321 // If we generated the funding transaction and it doesn't match what it
83058322 // should, the client is really broken and we should just panic and
83068323 // tell them off. That said, because hash collisions happen with high
@@ -8313,7 +8330,7 @@ impl<SP: Deref> FundedChannel<SP> where
83138330 let err_reason = "funding tx had wrong script/value or output index";
83148331 return Err(ClosureReason::ProcessingError { err: err_reason.to_owned() });
83158332 } else {
8316- if self. funding.is_outbound() {
8333+ if funding.is_outbound() {
83178334 if !tx.is_coinbase() {
83188335 for input in tx.input.iter() {
83198336 if input.witness.is_empty() {
@@ -8326,15 +8343,15 @@ impl<SP: Deref> FundedChannel<SP> where
83268343 }
83278344 }
83288345
8329- self. funding.funding_tx_confirmation_height = height;
8330- self. funding.funding_tx_confirmed_in = Some(*block_hash);
8331- self. funding.short_channel_id = match scid_from_parts(height as u64, index_in_block as u64, txo_idx as u64) {
8346+ funding.funding_tx_confirmation_height = height;
8347+ funding.funding_tx_confirmed_in = Some(*block_hash);
8348+ funding.short_channel_id = match scid_from_parts(height as u64, index_in_block as u64, txo_idx as u64) {
83328349 Ok(scid) => Some(scid),
83338350 Err(_) => panic!("Block was bogus - either height was > 16 million, had > 16 million transactions, or had > 65k outputs"),
83348351 };
83358352 }
83368353
8337- confirmed_funding = Some(ConfirmedFunding { funding_tx: &tx } );
8354+ confirmed_funding_tx = Some(tx );
83388355 }
83398356 }
83408357 for inp in tx.input.iter() {
@@ -8344,24 +8361,45 @@ impl<SP: Deref> FundedChannel<SP> where
83448361 }
83458362 }
83468363 }
8347- }
83488364
8349- if let Some(ConfirmedFunding { funding_tx }) = confirmed_funding {
8350- // If this is a coinbase transaction and not a 0-conf channel
8351- // we should update our min_depth to 100 to handle coinbase maturity
8352- if funding_tx.is_coinbase() &&
8353- self.funding.minimum_depth.unwrap_or(0) > 0 &&
8354- self.funding.minimum_depth.unwrap_or(0) < COINBASE_MATURITY {
8355- self.funding.minimum_depth = Some(COINBASE_MATURITY);
8365+ if let Some(funding_tx) = confirmed_funding_tx {
8366+ confirmed_funding = Some(ConfirmedFunding { funding, funding_tx });
83568367 }
8368+ }
83578369
8358- // If we allow 1-conf funding, we may need to check for channel_ready here and
8359- // send it immediately instead of waiting for a best_block_updated call (which
8360- // may have already happened for this block).
8361- if let Some(channel_ready) = self.check_get_channel_ready(height, logger) {
8362- log_info!(logger, "Sending a channel_ready to our peer for channel {}", &self.context.channel_id);
8363- let announcement_sigs = self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger);
8364- return Ok((Some(FundingConfirmedMessage::Establishment(channel_ready)), announcement_sigs));
8370+ // If we allow 1-conf funding, we may need to check for channel_ready or splice_locked here
8371+ // and send it immediately instead of waiting for a best_block_updated call (which may have
8372+ // already happened for this block).
8373+ if let Some(ConfirmedFunding { funding, funding_tx }) = confirmed_funding {
8374+ let confirmed_funding_txo = funding.get_funding_txo();
8375+ if confirmed_funding_txo == current_funding_txo {
8376+ // If this is a coinbase transaction and not a 0-conf channel
8377+ // we should update our min_depth to 100 to handle coinbase maturity
8378+ if funding_tx.is_coinbase() &&
8379+ funding.minimum_depth.unwrap_or(0) > 0 &&
8380+ funding.minimum_depth.unwrap_or(0) < COINBASE_MATURITY {
8381+ funding.minimum_depth = Some(COINBASE_MATURITY);
8382+ }
8383+
8384+ if let Some(channel_ready) = self.check_get_channel_ready(height, logger) {
8385+ log_info!(logger, "Sending a channel_ready to our peer for channel {}", &self.context.channel_id);
8386+ let announcement_sigs = self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger);
8387+ return Ok((Some(FundingConfirmedMessage::Establishment(channel_ready)), announcement_sigs));
8388+ }
8389+ } else {
8390+ #[cfg(splicing)] {
8391+ if let Some(pending_splice) = &mut self.pending_splice {
8392+ pending_splice.confirmed_funding_txid = confirmed_funding_txo.map(|txo| txo.txid);
8393+ debug_assert!(pending_splice.confirmed_funding_txid.is_some());
8394+ } else {
8395+ debug_assert!(false);
8396+ }
8397+ if let Some(splice_locked) = self.context.check_get_splice_locked(funding, height, logger) {
8398+ log_info!(logger, "Sending a splice_locked to our peer for channel {}", &self.context.channel_id);
8399+ let announcement_sigs = self.context.get_announcement_sigs(funding, node_signer, chain_hash, user_config, height, logger);
8400+ return Ok((Some(FundingConfirmedMessage::Splice(splice_locked)), announcement_sigs));
8401+ }
8402+ }
83658403 }
83668404 }
83678405
@@ -8458,6 +8496,27 @@ impl<SP: Deref> FundedChannel<SP> where
84588496 return Err(ClosureReason::FundingTimedOut);
84598497 }
84608498
8499+ if let Some(confirmed_funding_txid) = self.pending_splice
8500+ .as_ref()
8501+ .and_then(|pending_splice| pending_splice.confirmed_funding_txid)
8502+ {
8503+ if let Some((funding, _)) = self.pending_funding
8504+ .iter()
8505+ .filter_map(|funding| funding.get_funding_txo().map(|txo| (funding, txo.txid)))
8506+ .find(|(_, funding_txid)| *funding_txid == confirmed_funding_txid)
8507+ {
8508+ if let Some(splice_locked) = self.context.check_get_splice_locked(funding, height, logger) {
8509+ let announcement_sigs = if let Some((chain_hash, node_signer, user_config)) = chain_node_signer {
8510+ self.context.get_announcement_sigs(funding, node_signer, chain_hash, user_config, height, logger)
8511+ } else {
8512+ None
8513+ };
8514+ log_info!(logger, "Sending a splice_locked to our peer for channel {}", &self.context.channel_id);
8515+ return Ok((Some(FundingConfirmedMessage::Splice(splice_locked)), timed_out_htlcs, announcement_sigs));
8516+ }
8517+ }
8518+ }
8519+
84618520 let announcement_sigs = if let Some((chain_hash, node_signer, user_config)) = chain_node_signer {
84628521 self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger)
84638522 } else { None };
@@ -8704,6 +8763,7 @@ impl<SP: Deref> FundedChannel<SP> where
87048763
87058764 self.pending_splice = Some(PendingSplice {
87068765 our_funding_contribution: our_funding_contribution_satoshis,
8766+ confirmed_funding_txid: None,
87078767 });
87088768
87098769 let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw, locktime);
0 commit comments