@@ -1669,6 +1669,33 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
1669
1669
current_height, &broadcaster, &fee_estimator, &logger,
1670
1670
);
1671
1671
}
1672
+
1673
+ /// Returns the descriptors for relevant outputs (i.e., those that we can spend) within the
1674
+ /// transaction if they exist and the transaction has at least [`ANTI_REORG_DELAY`]
1675
+ /// confirmations.
1676
+ ///
1677
+ /// Descriptors returned by this method are primarily exposed via [`Event::SpendableOutputs`]
1678
+ /// once they are no longer under reorg risk. This method serves as a way to retrieve these
1679
+ /// descriptors at a later time, either for historical purposes, or to replay any
1680
+ /// missed/unhandled descriptors. For the purpose of gathering historical records, if the
1681
+ /// channel close has fully resolved (i.e., [`ChannelMonitor::get_claimable_balances`] returns
1682
+ /// an empty set), you can retrieve all spendable outputs by providing all descendant spending
1683
+ /// transactions starting from the channel's funding or closing transaction that have at least
1684
+ /// [`ANTI_REORG_DELAY`] confirmations.
1685
+ ///
1686
+ /// `tx` is a transaction we'll scan the outputs of. Any transaction can be provided. If any
1687
+ /// outputs which can be spent by us are found, at least one descriptor is returned.
1688
+ ///
1689
+ /// `confirmation_height` must be the height of the block in which `tx` was included in.
1690
+ pub fn get_spendable_outputs(&self, tx: &Transaction, confirmation_height: u32) -> Vec<SpendableOutputDescriptor> {
1691
+ let inner = self.inner.lock().unwrap();
1692
+ let current_height = inner.best_block.height;
1693
+ if current_height.saturating_sub(ANTI_REORG_DELAY) + 1 >= confirmation_height {
1694
+ inner.get_spendable_outputs(tx)
1695
+ } else {
1696
+ Vec::new()
1697
+ }
1698
+ }
1672
1699
}
1673
1700
1674
1701
impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
@@ -3441,7 +3468,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3441
3468
}
3442
3469
self.is_resolving_htlc_output(&tx, height, &block_hash, &logger);
3443
3470
3444
- self.is_paying_spendable_output (&tx, height, &block_hash, &logger);
3471
+ self.check_tx_and_push_spendable_outputs (&tx, height, &block_hash, &logger);
3445
3472
}
3446
3473
}
3447
3474
@@ -3987,34 +4014,18 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3987
4014
}
3988
4015
}
3989
4016
3990
- /// Check if any transaction broadcasted is paying fund back to some address we can assume to own
3991
- fn is_paying_spendable_output<L: Deref>(&mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &L) where L::Target: Logger {
3992
- let mut spendable_output = None;
3993
- for (i, outp) in tx.output.iter().enumerate() { // There is max one spendable output for any channel tx, including ones generated by us
3994
- if i > ::core::u16::MAX as usize {
3995
- // While it is possible that an output exists on chain which is greater than the
3996
- // 2^16th output in a given transaction, this is only possible if the output is not
3997
- // in a lightning transaction and was instead placed there by some third party who
3998
- // wishes to give us money for no reason.
3999
- // Namely, any lightning transactions which we pre-sign will never have anywhere
4000
- // near 2^16 outputs both because such transactions must have ~2^16 outputs who's
4001
- // scripts are not longer than one byte in length and because they are inherently
4002
- // non-standard due to their size.
4003
- // Thus, it is completely safe to ignore such outputs, and while it may result in
4004
- // us ignoring non-lightning fund to us, that is only possible if someone fills
4005
- // nearly a full block with garbage just to hit this case.
4006
- continue;
4007
- }
4017
+ fn get_spendable_outputs(&self, tx: &Transaction) -> Vec<SpendableOutputDescriptor> {
4018
+ let mut spendable_outputs = Vec::new();
4019
+ for (i, outp) in tx.output.iter().enumerate() {
4008
4020
if outp.script_pubkey == self.destination_script {
4009
- spendable_output = Some (SpendableOutputDescriptor::StaticOutput {
4021
+ spendable_outputs.push (SpendableOutputDescriptor::StaticOutput {
4010
4022
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
4011
4023
output: outp.clone(),
4012
4024
});
4013
- break;
4014
4025
}
4015
4026
if let Some(ref broadcasted_holder_revokable_script) = self.broadcasted_holder_revokable_script {
4016
4027
if broadcasted_holder_revokable_script.0 == outp.script_pubkey {
4017
- spendable_output = Some (SpendableOutputDescriptor::DelayedPaymentOutput(DelayedPaymentOutputDescriptor {
4028
+ spendable_outputs.push (SpendableOutputDescriptor::DelayedPaymentOutput(DelayedPaymentOutputDescriptor {
4018
4029
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
4019
4030
per_commitment_point: broadcasted_holder_revokable_script.1,
4020
4031
to_self_delay: self.on_holder_tx_csv,
@@ -4023,27 +4034,32 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
4023
4034
channel_keys_id: self.channel_keys_id,
4024
4035
channel_value_satoshis: self.channel_value_satoshis,
4025
4036
}));
4026
- break;
4027
4037
}
4028
4038
}
4029
4039
if self.counterparty_payment_script == outp.script_pubkey {
4030
- spendable_output = Some (SpendableOutputDescriptor::StaticPaymentOutput(StaticPaymentOutputDescriptor {
4040
+ spendable_outputs.push (SpendableOutputDescriptor::StaticPaymentOutput(StaticPaymentOutputDescriptor {
4031
4041
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
4032
4042
output: outp.clone(),
4033
4043
channel_keys_id: self.channel_keys_id,
4034
4044
channel_value_satoshis: self.channel_value_satoshis,
4035
4045
}));
4036
- break;
4037
4046
}
4038
4047
if self.shutdown_script.as_ref() == Some(&outp.script_pubkey) {
4039
- spendable_output = Some (SpendableOutputDescriptor::StaticOutput {
4048
+ spendable_outputs.push (SpendableOutputDescriptor::StaticOutput {
4040
4049
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
4041
4050
output: outp.clone(),
4042
4051
});
4043
- break;
4044
4052
}
4045
4053
}
4046
- if let Some(spendable_output) = spendable_output {
4054
+ spendable_outputs
4055
+ }
4056
+
4057
+ /// Checks if the confirmed transaction is paying funds back to some address we can assume to
4058
+ /// own.
4059
+ fn check_tx_and_push_spendable_outputs<L: Deref>(
4060
+ &mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &L,
4061
+ ) where L::Target: Logger {
4062
+ for spendable_output in self.get_spendable_outputs(tx) {
4047
4063
let entry = OnchainEventEntry {
4048
4064
txid: tx.txid(),
4049
4065
transaction: Some(tx.clone()),
0 commit comments