current_height, &broadcaster, &fee_estimator, &logger,
);
}
+
+ /// Returns the descriptor for a relevant output (i.e., one that we can spend) within the
+ /// transaction if one exists and the transaction has at least [`ANTI_REORG_DELAY`]
+ /// confirmations.
+ ///
+ /// Descriptors returned by this method are primarily exposed via [`Event::SpendableOutputs`]
+ /// once they are no longer under reorg risk. This method serves as a way to retrieve these
+ /// descriptors at a later time, either for historical purposes, or to replay any
+ /// missed/unhandled descriptors. For the purpose of gathering historical records, if the
+ /// channel close has fully resolved (i.e., [`ChannelMonitor::get_claimable_balances`] returns
+ /// an empty set), you can retrieve all spendable outputs by providing all descendant spending
+ /// transactions starting from the channel's funding or closing transaction that have at least
+ /// [`ANTI_REORG_DELAY`] confirmations.
+ ///
+ /// `tx` is a transaction we'll scan the outputs of. Any transaction can be provided. If an
+ /// output which can be spent by us is found, a descriptor is returned.
+ ///
+ /// `confirmation_height` must be the height of the block in which `tx` was included in.
+ pub fn get_spendable_output(&self, tx: &Transaction, confirmation_height: u32) -> Option<SpendableOutputDescriptor> {
+ let inner = self.inner.lock().unwrap();
+ let current_height = inner.best_block.height;
+ if current_height.saturating_sub(ANTI_REORG_DELAY) + 1 >= confirmation_height {
+ inner.get_spendable_output(tx)
+ } else {
+ None
+ }
+ }
}
impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
}
self.is_resolving_htlc_output(&tx, height, &block_hash, &logger);
- self.is_paying_spendable_output(&tx, height, &block_hash, &logger);
+ self.check_tx_and_push_spendable_output(&tx, height, &block_hash, &logger);
}
}
}
}
- /// Check if any transaction broadcasted is paying fund back to some address we can assume to own
- fn is_paying_spendable_output<L: Deref>(&mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &L) where L::Target: Logger {
- let mut spendable_output = None;
+ fn get_spendable_output(&self, tx: &Transaction) -> Option<SpendableOutputDescriptor> {
for (i, outp) in tx.output.iter().enumerate() { // There is max one spendable output for any channel tx, including ones generated by us
if i > ::core::u16::MAX as usize {
// While it is possible that an output exists on chain which is greater than the
continue;
}
if outp.script_pubkey == self.destination_script {
- spendable_output = Some(SpendableOutputDescriptor::StaticOutput {
+ return Some(SpendableOutputDescriptor::StaticOutput {
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
output: outp.clone(),
});
- break;
}
if let Some(ref broadcasted_holder_revokable_script) = self.broadcasted_holder_revokable_script {
if broadcasted_holder_revokable_script.0 == outp.script_pubkey {
- spendable_output = Some(SpendableOutputDescriptor::DelayedPaymentOutput(DelayedPaymentOutputDescriptor {
+ return Some(SpendableOutputDescriptor::DelayedPaymentOutput(DelayedPaymentOutputDescriptor {
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
per_commitment_point: broadcasted_holder_revokable_script.1,
to_self_delay: self.on_holder_tx_csv,
channel_keys_id: self.channel_keys_id,
channel_value_satoshis: self.channel_value_satoshis,
}));
- break;
}
}
if self.counterparty_payment_script == outp.script_pubkey {
- spendable_output = Some(SpendableOutputDescriptor::StaticPaymentOutput(StaticPaymentOutputDescriptor {
+ return Some(SpendableOutputDescriptor::StaticPaymentOutput(StaticPaymentOutputDescriptor {
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
output: outp.clone(),
channel_keys_id: self.channel_keys_id,
channel_value_satoshis: self.channel_value_satoshis,
}));
- break;
}
if self.shutdown_script.as_ref() == Some(&outp.script_pubkey) {
- spendable_output = Some(SpendableOutputDescriptor::StaticOutput {
+ return Some(SpendableOutputDescriptor::StaticOutput {
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
output: outp.clone(),
});
- break;
}
}
- if let Some(spendable_output) = spendable_output {
+ None
+ }
+
+ /// Checks if the confirmed transaction is paying funds back to some address we can assume to
+ /// own.
+ fn check_tx_and_push_spendable_output<L: Deref>(
+ &mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &L,
+ ) where L::Target: Logger {
+ if let Some(spendable_output) = self.get_spendable_output(tx) {
let entry = OnchainEventEntry {
txid: tx.txid(),
transaction: Some(tx.clone()),