);
}
- /// 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`]
+ /// Returns the descriptors for relevant outputs (i.e., those that we can spend) within the
+ /// transaction if they exist and the transaction has at least [`ANTI_REORG_DELAY`]
/// confirmations.
///
/// Descriptors returned by this method are primarily exposed via [`Event::SpendableOutputs`]
/// 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.
+ /// `tx` is a transaction we'll scan the outputs of. Any transaction can be provided. If any
+ /// outputs which can be spent by us are found, at least one 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> {
+ pub fn get_spendable_outputs(&self, tx: &Transaction, confirmation_height: u32) -> Vec<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)
+ inner.get_spendable_outputs(tx)
} else {
- None
+ Vec::new()
}
}
}
}
self.is_resolving_htlc_output(&tx, height, &block_hash, &logger);
- self.check_tx_and_push_spendable_output(&tx, height, &block_hash, &logger);
+ self.check_tx_and_push_spendable_outputs(&tx, height, &block_hash, &logger);
}
}
}
}
- 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
- // 2^16th output in a given transaction, this is only possible if the output is not
- // in a lightning transaction and was instead placed there by some third party who
- // wishes to give us money for no reason.
- // Namely, any lightning transactions which we pre-sign will never have anywhere
- // near 2^16 outputs both because such transactions must have ~2^16 outputs who's
- // scripts are not longer than one byte in length and because they are inherently
- // non-standard due to their size.
- // Thus, it is completely safe to ignore such outputs, and while it may result in
- // us ignoring non-lightning fund to us, that is only possible if someone fills
- // nearly a full block with garbage just to hit this case.
- continue;
- }
+ fn get_spendable_outputs(&self, tx: &Transaction) -> Vec<SpendableOutputDescriptor> {
+ let mut spendable_outputs = Vec::new();
+ for (i, outp) in tx.output.iter().enumerate() {
if outp.script_pubkey == self.destination_script {
- return Some(SpendableOutputDescriptor::StaticOutput {
+ spendable_outputs.push(SpendableOutputDescriptor::StaticOutput {
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
output: outp.clone(),
});
}
if let Some(ref broadcasted_holder_revokable_script) = self.broadcasted_holder_revokable_script {
if broadcasted_holder_revokable_script.0 == outp.script_pubkey {
- return Some(SpendableOutputDescriptor::DelayedPaymentOutput(DelayedPaymentOutputDescriptor {
+ spendable_outputs.push(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,
}
}
if self.counterparty_payment_script == outp.script_pubkey {
- return Some(SpendableOutputDescriptor::StaticPaymentOutput(StaticPaymentOutputDescriptor {
+ spendable_outputs.push(SpendableOutputDescriptor::StaticPaymentOutput(StaticPaymentOutputDescriptor {
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
output: outp.clone(),
channel_keys_id: self.channel_keys_id,
}));
}
if self.shutdown_script.as_ref() == Some(&outp.script_pubkey) {
- return Some(SpendableOutputDescriptor::StaticOutput {
+ spendable_outputs.push(SpendableOutputDescriptor::StaticOutput {
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
output: outp.clone(),
});
}
}
- None
+ spendable_outputs
}
/// 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>(
+ fn check_tx_and_push_spendable_outputs<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) {
+ for spendable_output in self.get_spendable_outputs(tx) {
let entry = OnchainEventEntry {
txid: tx.txid(),
transaction: Some(tx.clone()),