Skip to content

Commit 49bbe82

Browse files
committed
Track the tx which spends our funding output in ChannelMonitor
This allows us to easily look up how our channel was closed and track which balances may be spendable on-chain.
1 parent 4b523bb commit 49bbe82

File tree

1 file changed

+63
-18
lines changed

1 file changed

+63
-18
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -354,12 +354,20 @@ struct OnchainEventEntry {
354354
impl OnchainEventEntry {
355355
fn confirmation_threshold(&self) -> u32 {
356356
let mut conf_threshold = self.height + ANTI_REORG_DELAY - 1;
357-
if let OnchainEvent::MaturingOutput {
358-
descriptor: SpendableOutputDescriptor::DelayedPaymentOutput(ref descriptor)
359-
} = self.event {
360-
// A CSV'd transaction is confirmable in block (input height) + CSV delay, which means
361-
// it's broadcastable when we see the previous block.
362-
conf_threshold = cmp::max(conf_threshold, self.height + descriptor.to_self_delay as u32 - 1);
357+
match self.event {
358+
OnchainEvent::MaturingOutput {
359+
descriptor: SpendableOutputDescriptor::DelayedPaymentOutput(ref descriptor)
360+
} => {
361+
// A CSV'd transaction is confirmable in block (input height) + CSV delay, which means
362+
// it's broadcastable when we see the previous block.
363+
conf_threshold = cmp::max(conf_threshold, self.height + descriptor.to_self_delay as u32 - 1);
364+
},
365+
OnchainEvent::FundingSpendConfirmation { on_local_output_csv: Some(csv), .. } => {
366+
// A CSV'd transaction is confirmable in block (input height) + CSV delay, which means
367+
// it's broadcastable when we see the previous block.
368+
conf_threshold = cmp::max(conf_threshold, self.height + csv as u32 - 1);
369+
},
370+
_ => {},
363371
}
364372
conf_threshold
365373
}
@@ -383,6 +391,10 @@ enum OnchainEvent {
383391
MaturingOutput {
384392
descriptor: SpendableOutputDescriptor,
385393
},
394+
FundingSpendConfirmation {
395+
txid: Txid,
396+
on_local_output_csv: Option<u16>,
397+
},
386398
}
387399

388400
impl Writeable for OnchainEventEntry {
@@ -422,6 +434,10 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
422434
(1, MaturingOutput) => {
423435
(0, descriptor, required),
424436
},
437+
(3, FundingSpendConfirmation) => {
438+
(0, txid, required),
439+
(2, on_local_output_csv, option),
440+
},
425441
);
426442

427443
#[cfg_attr(any(test, feature = "fuzztarget", feature = "_test_utils"), derive(PartialEq))]
@@ -585,6 +601,8 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
585601
// remote monitor out-of-order with regards to the block view.
586602
holder_tx_signed: bool,
587603

604+
funding_spend_confirmed: Option<Txid>,
605+
588606
// We simply modify best_block in Channel's block_connected so that serialization is
589607
// consistent but hopefully the users' copy handles block_connected in a consistent way.
590608
// (we do *not*, however, update them in update_monitor to ensure any local user copies keep
@@ -643,7 +661,8 @@ impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
643661
self.onchain_events_awaiting_threshold_conf != other.onchain_events_awaiting_threshold_conf ||
644662
self.outputs_to_watch != other.outputs_to_watch ||
645663
self.lockdown_from_offchain != other.lockdown_from_offchain ||
646-
self.holder_tx_signed != other.holder_tx_signed
664+
self.holder_tx_signed != other.holder_tx_signed ||
665+
self.funding_spend_confirmed != other.funding_spend_confirmed
647666
{
648667
false
649668
} else {
@@ -805,7 +824,9 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
805824
self.lockdown_from_offchain.write(writer)?;
806825
self.holder_tx_signed.write(writer)?;
807826

808-
write_tlv_fields!(writer, {});
827+
write_tlv_fields!(writer, {
828+
(1, self.funding_spend_confirmed, option),
829+
});
809830

810831
Ok(())
811832
}
@@ -905,6 +926,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
905926

906927
lockdown_from_offchain: false,
907928
holder_tx_signed: false,
929+
funding_spend_confirmed: None,
908930

909931
best_block,
910932

@@ -1771,7 +1793,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
17711793
/// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet)
17721794
/// revoked using data in holder_claimable_outpoints.
17731795
/// Should not be used if check_spend_revoked_transaction succeeds.
1774-
fn check_spend_holder_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec<PackageTemplate>, TransactionOutputs) where L::Target: Logger {
1796+
/// Returns None unless the transaction is definitely one of our commitment transactions.
1797+
fn check_spend_holder_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> Option<(Vec<PackageTemplate>, TransactionOutputs)> where L::Target: Logger {
17751798
let commitment_txid = tx.txid();
17761799
let mut claim_requests = Vec::new();
17771800
let mut watch_outputs = Vec::new();
@@ -1806,9 +1829,10 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
18061829
}
18071830

18081831
if is_holder_tx {
1832+
Some((claim_requests, (commitment_txid, watch_outputs)))
1833+
} else {
1834+
None
18091835
}
1810-
1811-
(claim_requests, (commitment_txid, watch_outputs))
18121836
}
18131837

18141838
pub fn get_latest_holder_commitment_txn<L: Deref>(&mut self, logger: &L) -> Vec<Transaction> where L::Target: Logger {
@@ -1943,20 +1967,33 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
19431967
// filters.
19441968
let prevout = &tx.input[0].previous_output;
19451969
if prevout.txid == self.funding_info.0.txid && prevout.vout == self.funding_info.0.index as u32 {
1970+
let mut balance_spendable_csv = None;
1971+
log_info!(logger, "Channel closed by funding output spend in txid {}.", log_bytes!(tx.txid()));
19461972
if (tx.input[0].sequence >> 8*3) as u8 == 0x80 && (tx.lock_time >> 8*3) as u8 == 0x20 {
19471973
let (mut new_outpoints, new_outputs) = self.check_spend_counterparty_transaction(&tx, height, &logger);
19481974
if !new_outputs.1.is_empty() {
19491975
watch_outputs.push(new_outputs);
19501976
}
1977+
claimable_outpoints.append(&mut new_outpoints);
19511978
if new_outpoints.is_empty() {
1952-
let (mut new_outpoints, new_outputs) = self.check_spend_holder_transaction(&tx, height, &logger);
1953-
if !new_outputs.1.is_empty() {
1954-
watch_outputs.push(new_outputs);
1979+
if let Some((mut new_outpoints, new_outputs)) = self.check_spend_holder_transaction(&tx, height, &logger) {
1980+
if !new_outputs.1.is_empty() {
1981+
watch_outputs.push(new_outputs);
1982+
}
1983+
claimable_outpoints.append(&mut new_outpoints);
1984+
balance_spendable_csv = Some(self.on_holder_tx_csv);
19551985
}
1956-
claimable_outpoints.append(&mut new_outpoints);
19571986
}
1958-
claimable_outpoints.append(&mut new_outpoints);
19591987
}
1988+
let txid = tx.txid();
1989+
self.onchain_events_awaiting_threshold_conf.push(OnchainEventEntry {
1990+
txid,
1991+
height: height,
1992+
event: OnchainEvent::FundingSpendConfirmation {
1993+
txid,
1994+
on_local_output_csv: balance_spendable_csv,
1995+
},
1996+
});
19601997
} else {
19611998
if let Some(&commitment_number) = self.counterparty_commitment_txn_on_chain.get(&prevout.txid) {
19621999
let (mut new_outpoints, new_outputs_option) = self.check_spend_counterparty_htlc(&tx, commitment_number, height, &logger);
@@ -2044,6 +2081,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
20442081
.filter_map(|entry| match &entry.event {
20452082
OnchainEvent::HTLCUpdate { source, .. } => Some(source),
20462083
OnchainEvent::MaturingOutput { .. } => None,
2084+
OnchainEvent::FundingSpendConfirmation { .. } => None,
20472085
})
20482086
.collect();
20492087
#[cfg(debug_assertions)]
@@ -2081,7 +2119,10 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
20812119
self.pending_events.push(Event::SpendableOutputs {
20822120
outputs: vec![descriptor]
20832121
});
2084-
}
2122+
},
2123+
OnchainEvent::FundingSpendConfirmation { txid, .. } => {
2124+
self.funding_spend_confirmed = Some(txid);
2125+
},
20852126
}
20862127
}
20872128

@@ -2748,7 +2789,10 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
27482789
return Err(DecodeError::InvalidValue);
27492790
}
27502791

2751-
read_tlv_fields!(reader, {});
2792+
let mut funding_spend_confirmed = None;
2793+
read_tlv_fields!(reader, {
2794+
(1, funding_spend_confirmed, option),
2795+
});
27522796

27532797
let mut secp_ctx = Secp256k1::new();
27542798
secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes());
@@ -2797,6 +2841,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
27972841

27982842
lockdown_from_offchain,
27992843
holder_tx_signed,
2844+
funding_spend_confirmed,
28002845

28012846
best_block,
28022847

0 commit comments

Comments
 (0)