Skip to content

Commit 9a6340f

Browse files
committed
WIP: Check all funding transactions
1 parent f5f3c5a commit 9a6340f

File tree

2 files changed

+89
-25
lines changed

2 files changed

+89
-25
lines changed

lightning/src/ln/channel.rs

+85-25
Original file line numberDiff line numberDiff line change
@@ -1864,6 +1864,7 @@ impl FundingScope {
18641864
#[cfg(splicing)]
18651865
struct 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);

lightning/src/ln/channelmanager.rs

+4
Original file line numberDiff line numberDiff line change
@@ -11664,6 +11664,8 @@ where
1166411664

1166511665
pub(super) enum FundingConfirmedMessage {
1166611666
Establishment(msgs::ChannelReady),
11667+
#[cfg(splicing)]
11668+
Splice(msgs::SpliceLocked),
1166711669
}
1166811670

1166911671
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, MR: Deref, L: Deref> ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
@@ -11725,6 +11727,8 @@ where
1172511727
log_trace!(logger, "Sending channel_ready WITHOUT channel_update for {}", funded_channel.context.channel_id());
1172611728
}
1172711729
},
11730+
#[cfg(splicing)]
11731+
Some(FundingConfirmedMessage::Splice(splice_locked)) => {},
1172811732
None => {}
1172911733
}
1173011734

0 commit comments

Comments
 (0)