Skip to content

Commit 73ee30d

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 cd578b5 commit 73ee30d

File tree

1 file changed

+67
-18
lines changed

1 file changed

+67
-18
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,20 @@ struct OnchainEventEntry {
356356
impl OnchainEventEntry {
357357
fn confirmation_threshold(&self) -> u32 {
358358
let mut conf_threshold = self.height + ANTI_REORG_DELAY - 1;
359-
if let OnchainEvent::MaturingOutput {
360-
descriptor: SpendableOutputDescriptor::DelayedPaymentOutput(ref descriptor)
361-
} = self.event {
362-
// A CSV'd transaction is confirmable in block (input height) + CSV delay, which means
363-
// it's broadcastable when we see the previous block.
364-
conf_threshold = cmp::max(conf_threshold, self.height + descriptor.to_self_delay as u32 - 1);
359+
match self.event {
360+
OnchainEvent::MaturingOutput {
361+
descriptor: SpendableOutputDescriptor::DelayedPaymentOutput(ref descriptor)
362+
} => {
363+
// A CSV'd transaction is confirmable in block (input height) + CSV delay, which means
364+
// it's broadcastable when we see the previous block.
365+
conf_threshold = cmp::max(conf_threshold, self.height + descriptor.to_self_delay as u32 - 1);
366+
},
367+
OnchainEvent::FundingSpendConfirmation { on_local_output_csv: Some(csv), .. } => {
368+
// A CSV'd transaction is confirmable in block (input height) + CSV delay, which means
369+
// it's broadcastable when we see the previous block.
370+
conf_threshold = cmp::max(conf_threshold, self.height + csv as u32 - 1);
371+
},
372+
_ => {},
365373
}
366374
conf_threshold
367375
}
@@ -386,6 +394,14 @@ enum OnchainEvent {
386394
MaturingOutput {
387395
descriptor: SpendableOutputDescriptor,
388396
},
397+
/// A spend of the funding output, either a commitment transaction or a cooperative closing
398+
/// transaction.
399+
FundingSpendConfirmation {
400+
txid: Txid,
401+
/// The CSV delay for the output of the funding spend transaction (implying it is a local
402+
/// commitment transaction, and this is the delay on the to_self output).
403+
on_local_output_csv: Option<u16>,
404+
},
389405
}
390406

391407
impl Writeable for OnchainEventEntry {
@@ -426,6 +442,10 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
426442
(1, MaturingOutput) => {
427443
(0, descriptor, required),
428444
},
445+
(3, FundingSpendConfirmation) => {
446+
(0, txid, required),
447+
(2, on_local_output_csv, option),
448+
},
429449
);
430450

431451
#[cfg_attr(any(test, feature = "fuzztarget", feature = "_test_utils"), derive(PartialEq))]
@@ -598,6 +618,8 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
598618
// remote monitor out-of-order with regards to the block view.
599619
holder_tx_signed: bool,
600620

621+
funding_spend_confirmed: Option<Txid>,
622+
601623
// We simply modify best_block in Channel's block_connected so that serialization is
602624
// consistent but hopefully the users' copy handles block_connected in a consistent way.
603625
// (we do *not*, however, update them in update_monitor to ensure any local user copies keep
@@ -656,7 +678,8 @@ impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
656678
self.onchain_events_awaiting_threshold_conf != other.onchain_events_awaiting_threshold_conf ||
657679
self.outputs_to_watch != other.outputs_to_watch ||
658680
self.lockdown_from_offchain != other.lockdown_from_offchain ||
659-
self.holder_tx_signed != other.holder_tx_signed
681+
self.holder_tx_signed != other.holder_tx_signed ||
682+
self.funding_spend_confirmed != other.funding_spend_confirmed
660683
{
661684
false
662685
} else {
@@ -821,7 +844,9 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
821844
self.lockdown_from_offchain.write(writer)?;
822845
self.holder_tx_signed.write(writer)?;
823846

824-
write_tlv_fields!(writer, {});
847+
write_tlv_fields!(writer, {
848+
(1, self.funding_spend_confirmed, option),
849+
});
825850

826851
Ok(())
827852
}
@@ -919,6 +944,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
919944

920945
lockdown_from_offchain: false,
921946
holder_tx_signed: false,
947+
funding_spend_confirmed: None,
922948

923949
best_block,
924950

@@ -1804,7 +1830,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
18041830
/// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet)
18051831
/// revoked using data in holder_claimable_outpoints.
18061832
/// Should not be used if check_spend_revoked_transaction succeeds.
1807-
fn check_spend_holder_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec<PackageTemplate>, TransactionOutputs) where L::Target: Logger {
1833+
/// Returns None unless the transaction is definitely one of our commitment transactions.
1834+
fn check_spend_holder_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> Option<(Vec<PackageTemplate>, TransactionOutputs)> where L::Target: Logger {
18081835
let commitment_txid = tx.txid();
18091836
let mut claim_requests = Vec::new();
18101837
let mut watch_outputs = Vec::new();
@@ -1839,9 +1866,10 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
18391866
}
18401867

18411868
if is_holder_tx {
1869+
Some((claim_requests, (commitment_txid, watch_outputs)))
1870+
} else {
1871+
None
18421872
}
1843-
1844-
(claim_requests, (commitment_txid, watch_outputs))
18451873
}
18461874

18471875
pub fn get_latest_holder_commitment_txn<L: Deref>(&mut self, logger: &L) -> Vec<Transaction> where L::Target: Logger {
@@ -1973,20 +2001,33 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
19732001
// filters.
19742002
let prevout = &tx.input[0].previous_output;
19752003
if prevout.txid == self.funding_info.0.txid && prevout.vout == self.funding_info.0.index as u32 {
2004+
let mut balance_spendable_csv = None;
2005+
log_info!(logger, "Channel closed by funding output spend in txid {}.", log_bytes!(tx.txid()));
19762006
if (tx.input[0].sequence >> 8*3) as u8 == 0x80 && (tx.lock_time >> 8*3) as u8 == 0x20 {
19772007
let (mut new_outpoints, new_outputs) = self.check_spend_counterparty_transaction(&tx, height, &logger);
19782008
if !new_outputs.1.is_empty() {
19792009
watch_outputs.push(new_outputs);
19802010
}
2011+
claimable_outpoints.append(&mut new_outpoints);
19812012
if new_outpoints.is_empty() {
1982-
let (mut new_outpoints, new_outputs) = self.check_spend_holder_transaction(&tx, height, &logger);
1983-
if !new_outputs.1.is_empty() {
1984-
watch_outputs.push(new_outputs);
2013+
if let Some((mut new_outpoints, new_outputs)) = self.check_spend_holder_transaction(&tx, height, &logger) {
2014+
if !new_outputs.1.is_empty() {
2015+
watch_outputs.push(new_outputs);
2016+
}
2017+
claimable_outpoints.append(&mut new_outpoints);
2018+
balance_spendable_csv = Some(self.on_holder_tx_csv);
19852019
}
1986-
claimable_outpoints.append(&mut new_outpoints);
19872020
}
1988-
claimable_outpoints.append(&mut new_outpoints);
19892021
}
2022+
let txid = tx.txid();
2023+
self.onchain_events_awaiting_threshold_conf.push(OnchainEventEntry {
2024+
txid,
2025+
height: height,
2026+
event: OnchainEvent::FundingSpendConfirmation {
2027+
txid,
2028+
on_local_output_csv: balance_spendable_csv,
2029+
},
2030+
});
19902031
} else {
19912032
if let Some(&commitment_number) = self.counterparty_commitment_txn_on_chain.get(&prevout.txid) {
19922033
let (mut new_outpoints, new_outputs_option) = self.check_spend_counterparty_htlc(&tx, commitment_number, height, &logger);
@@ -2075,6 +2116,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
20752116
.filter_map(|entry| match &entry.event {
20762117
OnchainEvent::HTLCUpdate { source, .. } => Some(source),
20772118
OnchainEvent::MaturingOutput { .. } => None,
2119+
OnchainEvent::FundingSpendConfirmation { .. } => None,
20782120
})
20792121
.collect();
20802122
#[cfg(debug_assertions)]
@@ -2113,7 +2155,10 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
21132155
self.pending_events.push(Event::SpendableOutputs {
21142156
outputs: vec![descriptor]
21152157
});
2116-
}
2158+
},
2159+
OnchainEvent::FundingSpendConfirmation { txid, .. } => {
2160+
self.funding_spend_confirmed = Some(txid);
2161+
},
21172162
}
21182163
}
21192164

@@ -2788,7 +2833,10 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
27882833
return Err(DecodeError::InvalidValue);
27892834
}
27902835

2791-
read_tlv_fields!(reader, {});
2836+
let mut funding_spend_confirmed = None;
2837+
read_tlv_fields!(reader, {
2838+
(1, funding_spend_confirmed, option),
2839+
});
27922840

27932841
let mut secp_ctx = Secp256k1::new();
27942842
secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes());
@@ -2837,6 +2885,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
28372885

28382886
lockdown_from_offchain,
28392887
holder_tx_signed,
2888+
funding_spend_confirmed,
28402889

28412890
best_block,
28422891

0 commit comments

Comments
 (0)