/// 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. For [`SpendableOutputDescriptor::DelayedPaymentOutput`] descriptors to be
+ /// returned, the transaction must have at least `max(ANTI_REORG_DELAY, to_self_delay)`
/// confirmations.
///
/// Descriptors returned by this method are primarily exposed via [`Event::SpendableOutputs`]
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_outputs(tx)
- } else {
- Vec::new()
- }
+ let mut spendable_outputs = inner.get_spendable_outputs(tx);
+ spendable_outputs.retain(|descriptor| {
+ let mut conf_threshold = current_height.saturating_sub(ANTI_REORG_DELAY) + 1;
+ if let SpendableOutputDescriptor::DelayedPaymentOutput(descriptor) = descriptor {
+ conf_threshold = cmp::min(conf_threshold,
+ current_height.saturating_sub(descriptor.to_self_delay as u32) + 1);
+ }
+ conf_threshold >= confirmation_height
+ });
+ spendable_outputs
}
}
// First confirm the commitment transaction on nodes[0], which should leave us with three
// claimable balances.
let node_a_commitment_claimable = nodes[0].best_block_info().1 + BREAKDOWN_TIMEOUT as u32;
- mine_transaction(&nodes[0], &as_txn[0]);
+ let commitment_tx_conf_height_a = block_from_scid(&mine_transaction(&nodes[0], &as_txn[0]));
check_added_monitors!(nodes[0], 1);
check_closed_broadcast!(nodes[0], true);
check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 1000000);
// Connect blocks until the commitment transaction's CSV expires, providing us the relevant
// `SpendableOutputs` event and removing the claimable balance entry.
- connect_blocks(&nodes[0], node_a_commitment_claimable - nodes[0].best_block_info().1);
+ connect_blocks(&nodes[0], node_a_commitment_claimable - nodes[0].best_block_info().1 - 1);
+ assert!(get_monitor!(nodes[0], chan_id)
+ .get_spendable_outputs(&as_txn[0], commitment_tx_conf_height_a).is_empty());
+ connect_blocks(&nodes[0], 1);
assert_eq!(vec![Balance::ClaimableAwaitingConfirmations {
amount_satoshis: 10_000,
confirmation_height: node_a_htlc_claimable,
}],
nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances());
- test_spendable_output(&nodes[0], &as_txn[0]);
+ let to_self_spendable_output = test_spendable_output(&nodes[0], &as_txn[0]);
+ assert_eq!(
+ get_monitor!(nodes[0], chan_id).get_spendable_outputs(&as_txn[0], commitment_tx_conf_height_a),
+ to_self_spendable_output
+ );
// Connect blocks until the HTLC-Timeout's CSV expires, providing us the relevant
// `SpendableOutputs` event and removing the claimable balance entry.