@@ -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 descriptor for a relevant output (i.e., one that we can spend) within the
1674
+ /// transaction if one exists 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 an
1687
+ /// output which can be spent by us is found, a 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_output ( & self , tx : & Transaction , confirmation_height : u32 ) -> Option < 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_output ( tx)
1695
+ } else {
1696
+ None
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_output ( & tx, height, & block_hash, & logger) ;
3445
3472
}
3446
3473
}
3447
3474
@@ -3987,9 +4014,7 @@ 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 ;
4017
+ fn get_spendable_output ( & self , tx : & Transaction ) -> Option < SpendableOutputDescriptor > {
3993
4018
for ( i, outp) in tx. output . iter ( ) . enumerate ( ) { // There is max one spendable output for any channel tx, including ones generated by us
3994
4019
if i > :: core:: u16:: MAX as usize {
3995
4020
// While it is possible that an output exists on chain which is greater than the
@@ -4006,15 +4031,14 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
4006
4031
continue ;
4007
4032
}
4008
4033
if outp. script_pubkey == self . destination_script {
4009
- spendable_output = Some ( SpendableOutputDescriptor :: StaticOutput {
4034
+ return Some ( SpendableOutputDescriptor :: StaticOutput {
4010
4035
outpoint : OutPoint { txid : tx. txid ( ) , index : i as u16 } ,
4011
4036
output : outp. clone ( ) ,
4012
4037
} ) ;
4013
- break ;
4014
4038
}
4015
4039
if let Some ( ref broadcasted_holder_revokable_script) = self . broadcasted_holder_revokable_script {
4016
4040
if broadcasted_holder_revokable_script. 0 == outp. script_pubkey {
4017
- spendable_output = Some ( SpendableOutputDescriptor :: DelayedPaymentOutput ( DelayedPaymentOutputDescriptor {
4041
+ return Some ( SpendableOutputDescriptor :: DelayedPaymentOutput ( DelayedPaymentOutputDescriptor {
4018
4042
outpoint : OutPoint { txid : tx. txid ( ) , index : i as u16 } ,
4019
4043
per_commitment_point : broadcasted_holder_revokable_script. 1 ,
4020
4044
to_self_delay : self . on_holder_tx_csv ,
@@ -4023,27 +4047,32 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
4023
4047
channel_keys_id : self . channel_keys_id ,
4024
4048
channel_value_satoshis : self . channel_value_satoshis ,
4025
4049
} ) ) ;
4026
- break ;
4027
4050
}
4028
4051
}
4029
4052
if self . counterparty_payment_script == outp. script_pubkey {
4030
- spendable_output = Some ( SpendableOutputDescriptor :: StaticPaymentOutput ( StaticPaymentOutputDescriptor {
4053
+ return Some ( SpendableOutputDescriptor :: StaticPaymentOutput ( StaticPaymentOutputDescriptor {
4031
4054
outpoint : OutPoint { txid : tx. txid ( ) , index : i as u16 } ,
4032
4055
output : outp. clone ( ) ,
4033
4056
channel_keys_id : self . channel_keys_id ,
4034
4057
channel_value_satoshis : self . channel_value_satoshis ,
4035
4058
} ) ) ;
4036
- break ;
4037
4059
}
4038
4060
if self . shutdown_script . as_ref ( ) == Some ( & outp. script_pubkey ) {
4039
- spendable_output = Some ( SpendableOutputDescriptor :: StaticOutput {
4061
+ return Some ( SpendableOutputDescriptor :: StaticOutput {
4040
4062
outpoint : OutPoint { txid : tx. txid ( ) , index : i as u16 } ,
4041
4063
output : outp. clone ( ) ,
4042
4064
} ) ;
4043
- break ;
4044
4065
}
4045
4066
}
4046
- if let Some ( spendable_output) = spendable_output {
4067
+ None
4068
+ }
4069
+
4070
+ /// Checks if the confirmed transaction is paying funds back to some address we can assume to
4071
+ /// own.
4072
+ fn check_tx_and_push_spendable_output < L : Deref > (
4073
+ & mut self , tx : & Transaction , height : u32 , block_hash : & BlockHash , logger : & L ,
4074
+ ) where L :: Target : Logger {
4075
+ if let Some ( spendable_output) = self . get_spendable_output ( tx) {
4047
4076
let entry = OnchainEventEntry {
4048
4077
txid : tx. txid ( ) ,
4049
4078
transaction : Some ( tx. clone ( ) ) ,
0 commit comments