@@ -1864,6 +1864,7 @@ impl FundingScope {
1864
1864
#[cfg(splicing)]
1865
1865
struct PendingSplice {
1866
1866
pub our_funding_contribution: i64,
1867
+ confirmed_funding_txid: Option<Txid>,
1867
1868
}
1868
1869
1869
1870
/// Contains everything about the channel including state, and various flags.
@@ -4967,6 +4968,13 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
4967
4968
_ => todo!()
4968
4969
}
4969
4970
}
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
+ }
4970
4978
}
4971
4979
4972
4980
// Internal utility functions for channels
@@ -8287,20 +8295,29 @@ impl<SP: Deref> FundedChannel<SP> where
8287
8295
L::Target: Logger
8288
8296
{
8289
8297
struct ConfirmedFunding<'a> {
8298
+ funding: &'a mut FundingScope,
8290
8299
funding_tx: &'a Transaction,
8291
8300
}
8292
8301
8293
8302
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))) {
8295
8307
for &(index_in_block, tx) in txdata.iter() {
8296
8308
// Check if the transaction is the expected funding transaction, and if it is,
8297
8309
// 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 {
8299
8311
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
+
8300
8317
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() {
8304
8321
// If we generated the funding transaction and it doesn't match what it
8305
8322
// should, the client is really broken and we should just panic and
8306
8323
// tell them off. That said, because hash collisions happen with high
@@ -8313,7 +8330,7 @@ impl<SP: Deref> FundedChannel<SP> where
8313
8330
let err_reason = "funding tx had wrong script/value or output index";
8314
8331
return Err(ClosureReason::ProcessingError { err: err_reason.to_owned() });
8315
8332
} else {
8316
- if self. funding.is_outbound() {
8333
+ if funding.is_outbound() {
8317
8334
if !tx.is_coinbase() {
8318
8335
for input in tx.input.iter() {
8319
8336
if input.witness.is_empty() {
@@ -8326,15 +8343,15 @@ impl<SP: Deref> FundedChannel<SP> where
8326
8343
}
8327
8344
}
8328
8345
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) {
8332
8349
Ok(scid) => Some(scid),
8333
8350
Err(_) => panic!("Block was bogus - either height was > 16 million, had > 16 million transactions, or had > 65k outputs"),
8334
8351
};
8335
8352
}
8336
8353
8337
- confirmed_funding = Some(ConfirmedFunding { funding_tx: &tx } );
8354
+ confirmed_funding_tx = Some(tx );
8338
8355
}
8339
8356
}
8340
8357
for inp in tx.input.iter() {
@@ -8344,24 +8361,45 @@ impl<SP: Deref> FundedChannel<SP> where
8344
8361
}
8345
8362
}
8346
8363
}
8347
- }
8348
8364
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 });
8356
8367
}
8368
+ }
8357
8369
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
+ }
8365
8403
}
8366
8404
}
8367
8405
@@ -8458,6 +8496,27 @@ impl<SP: Deref> FundedChannel<SP> where
8458
8496
return Err(ClosureReason::FundingTimedOut);
8459
8497
}
8460
8498
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
+
8461
8520
let announcement_sigs = if let Some((chain_hash, node_signer, user_config)) = chain_node_signer {
8462
8521
self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger)
8463
8522
} else { None };
@@ -8704,6 +8763,7 @@ impl<SP: Deref> FundedChannel<SP> where
8704
8763
8705
8764
self.pending_splice = Some(PendingSplice {
8706
8765
our_funding_contribution: our_funding_contribution_satoshis,
8766
+ confirmed_funding_txid: None,
8707
8767
});
8708
8768
8709
8769
let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw, locktime);
0 commit comments