Skip to content

Commit 1f915c7

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 d356b97 commit 1f915c7

File tree

1 file changed

+63
-18
lines changed

1 file changed

+63
-18
lines changed

lightning/src/chain/channelmonitor.rs

+63-18
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,10 @@ enum OnchainEvent {
386394
MaturingOutput {
387395
descriptor: SpendableOutputDescriptor,
388396
},
397+
FundingSpendConfirmation {
398+
txid: Txid,
399+
on_local_output_csv: Option<u16>,
400+
},
389401
}
390402

391403
impl Writeable for OnchainEventEntry {
@@ -426,6 +438,10 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
426438
(1, MaturingOutput) => {
427439
(0, descriptor, required),
428440
},
441+
(3, FundingSpendConfirmation) => {
442+
(0, txid, required),
443+
(2, on_local_output_csv, option),
444+
},
429445
);
430446

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

617+
funding_spend_confirmed: Option<Txid>,
618+
601619
// We simply modify best_block in Channel's block_connected so that serialization is
602620
// consistent but hopefully the users' copy handles block_connected in a consistent way.
603621
// (we do *not*, however, update them in update_monitor to ensure any local user copies keep
@@ -656,7 +674,8 @@ impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
656674
self.onchain_events_awaiting_threshold_conf != other.onchain_events_awaiting_threshold_conf ||
657675
self.outputs_to_watch != other.outputs_to_watch ||
658676
self.lockdown_from_offchain != other.lockdown_from_offchain ||
659-
self.holder_tx_signed != other.holder_tx_signed
677+
self.holder_tx_signed != other.holder_tx_signed ||
678+
self.funding_spend_confirmed != other.funding_spend_confirmed
660679
{
661680
false
662681
} else {
@@ -821,7 +840,9 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
821840
self.lockdown_from_offchain.write(writer)?;
822841
self.holder_tx_signed.write(writer)?;
823842

824-
write_tlv_fields!(writer, {});
843+
write_tlv_fields!(writer, {
844+
(1, self.funding_spend_confirmed, option),
845+
});
825846

826847
Ok(())
827848
}
@@ -919,6 +940,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
919940

920941
lockdown_from_offchain: false,
921942
holder_tx_signed: false,
943+
funding_spend_confirmed: None,
922944

923945
best_block,
924946

@@ -1804,7 +1826,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
18041826
/// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet)
18051827
/// revoked using data in holder_claimable_outpoints.
18061828
/// 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 {
1829+
/// Returns None unless the transaction is definitely one of our commitment transactions.
1830+
fn check_spend_holder_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> Option<(Vec<PackageTemplate>, TransactionOutputs)> where L::Target: Logger {
18081831
let commitment_txid = tx.txid();
18091832
let mut claim_requests = Vec::new();
18101833
let mut watch_outputs = Vec::new();
@@ -1839,9 +1862,10 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
18391862
}
18401863

18411864
if is_holder_tx {
1865+
Some((claim_requests, (commitment_txid, watch_outputs)))
1866+
} else {
1867+
None
18421868
}
1843-
1844-
(claim_requests, (commitment_txid, watch_outputs))
18451869
}
18461870

18471871
pub fn get_latest_holder_commitment_txn<L: Deref>(&mut self, logger: &L) -> Vec<Transaction> where L::Target: Logger {
@@ -1976,20 +2000,33 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
19762000
// filters.
19772001
let prevout = &tx.input[0].previous_output;
19782002
if prevout.txid == self.funding_info.0.txid && prevout.vout == self.funding_info.0.index as u32 {
2003+
let mut balance_spendable_csv = None;
2004+
log_info!(logger, "Channel closed by funding output spend in txid {}.", log_bytes!(tx.txid()));
19792005
if (tx.input[0].sequence >> 8*3) as u8 == 0x80 && (tx.lock_time >> 8*3) as u8 == 0x20 {
19802006
let (mut new_outpoints, new_outputs) = self.check_spend_counterparty_transaction(&tx, height, &logger);
19812007
if !new_outputs.1.is_empty() {
19822008
watch_outputs.push(new_outputs);
19832009
}
2010+
claimable_outpoints.append(&mut new_outpoints);
19842011
if new_outpoints.is_empty() {
1985-
let (mut new_outpoints, new_outputs) = self.check_spend_holder_transaction(&tx, height, &logger);
1986-
if !new_outputs.1.is_empty() {
1987-
watch_outputs.push(new_outputs);
2012+
if let Some((mut new_outpoints, new_outputs)) = self.check_spend_holder_transaction(&tx, height, &logger) {
2013+
if !new_outputs.1.is_empty() {
2014+
watch_outputs.push(new_outputs);
2015+
}
2016+
claimable_outpoints.append(&mut new_outpoints);
2017+
balance_spendable_csv = Some(self.on_holder_tx_csv);
19882018
}
1989-
claimable_outpoints.append(&mut new_outpoints);
19902019
}
1991-
claimable_outpoints.append(&mut new_outpoints);
19922020
}
2021+
let txid = tx.txid();
2022+
self.onchain_events_awaiting_threshold_conf.push(OnchainEventEntry {
2023+
txid,
2024+
height: height,
2025+
event: OnchainEvent::FundingSpendConfirmation {
2026+
txid,
2027+
on_local_output_csv: balance_spendable_csv,
2028+
},
2029+
});
19932030
} else {
19942031
if let Some(&commitment_number) = self.counterparty_commitment_txn_on_chain.get(&prevout.txid) {
19952032
let (mut new_outpoints, new_outputs_option) = self.check_spend_counterparty_htlc(&tx, commitment_number, height, &logger);
@@ -2077,6 +2114,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
20772114
.filter_map(|entry| match &entry.event {
20782115
OnchainEvent::HTLCUpdate { source, .. } => Some(source),
20792116
OnchainEvent::MaturingOutput { .. } => None,
2117+
OnchainEvent::FundingSpendConfirmation { .. } => None,
20802118
})
20812119
.collect();
20822120
#[cfg(debug_assertions)]
@@ -2115,7 +2153,10 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
21152153
self.pending_events.push(Event::SpendableOutputs {
21162154
outputs: vec![descriptor]
21172155
});
2118-
}
2156+
},
2157+
OnchainEvent::FundingSpendConfirmation { txid, .. } => {
2158+
self.funding_spend_confirmed = Some(txid);
2159+
},
21192160
}
21202161
}
21212162

@@ -2790,7 +2831,10 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
27902831
return Err(DecodeError::InvalidValue);
27912832
}
27922833

2793-
read_tlv_fields!(reader, {});
2834+
let mut funding_spend_confirmed = None;
2835+
read_tlv_fields!(reader, {
2836+
(1, funding_spend_confirmed, option),
2837+
});
27942838

27952839
let mut secp_ctx = Secp256k1::new();
27962840
secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes());
@@ -2839,6 +2883,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
28392883

28402884
lockdown_from_offchain,
28412885
holder_tx_signed,
2886+
funding_spend_confirmed,
28422887

28432888
best_block,
28442889

0 commit comments

Comments
 (0)