2222
2323use bitcoin:: blockdata:: block:: BlockHeader ;
2424use bitcoin:: blockdata:: transaction:: { TxOut , Transaction } ;
25+ use bitcoin:: blockdata:: transaction:: OutPoint as BitcoinOutPoint ;
2526use bitcoin:: blockdata:: script:: { Script , Builder } ;
2627use bitcoin:: blockdata:: opcodes;
2728
@@ -382,6 +383,9 @@ enum OnchainEvent {
382383 on_local_output_csv : Option < u16 > ,
383384 /// If the funding spend transaction was a known remote commitment transaction, we track
384385 /// the output index and amount of the counterparty's `to_self` output here.
386+ ///
387+ /// This allows us to generate a [`Balance::CounterpartyRevokedOutputClaimable`] for the
388+ /// counterparty output.
385389 commitment_tx_to_counterparty_output : CommitmentTxCounterpartyOutputInfo ,
386390 } ,
387391 /// A spend of a commitment transaction HTLC output, set in the cases where *no* `HTLCUpdate`
@@ -582,6 +586,18 @@ pub enum Balance {
582586 /// done so.
583587 claimable_height : u32 ,
584588 } ,
589+ /// The channel has been closed, and our counterparty broadcasted a revoked commitment
590+ /// transaction.
591+ ///
592+ /// Thus, we're able to claim all outputs in the commitment transaction, one of which has the
593+ /// following amount.
594+ CounterpartyRevokedOutputClaimable {
595+ /// The amount, in satoshis, of the output which we can claim.
596+ ///
597+ /// Note that for outputs from HTLC balances this may be excluding some on-chain fees that
598+ /// were already spent.
599+ claimable_amount_satoshis : u64 ,
600+ } ,
585601}
586602
587603/// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY.
@@ -1421,9 +1437,9 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
14211437 /// balance, or until our counterparty has claimed the balance and accrued several
14221438 /// confirmations on the claim transaction.
14231439 ///
1424- /// Note that the balances available when you or your counterparty have broadcasted revoked
1425- /// state(s) may not be fully captured here.
1426- // TODO, fix that ^
1440+ /// Note that for `ChannelMonitors` which track a channel which went on-chain with versions of
1441+ /// LDK prior to 0.0.108, balances may not be fully captured if our counterparty broadcasted
1442+ /// a revoked state.
14271443 ///
14281444 /// See [`Balance`] for additional details on the types of claimable balances which
14291445 /// may be returned here and their meanings.
@@ -1432,9 +1448,13 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
14321448 let us = self . inner . lock ( ) . unwrap ( ) ;
14331449
14341450 let mut confirmed_txid = us. funding_spend_confirmed ;
1451+ let mut confirmed_counterparty_output = us. confirmed_commitment_tx_counterparty_output ;
14351452 let mut pending_commitment_tx_conf_thresh = None ;
14361453 let funding_spend_pending = us. onchain_events_awaiting_threshold_conf . iter ( ) . find_map ( |event| {
1437- if let OnchainEvent :: FundingSpendConfirmation { .. } = event. event {
1454+ if let OnchainEvent :: FundingSpendConfirmation { commitment_tx_to_counterparty_output, .. } =
1455+ event. event
1456+ {
1457+ confirmed_counterparty_output = commitment_tx_to_counterparty_output;
14381458 Some ( ( event. txid , event. confirmation_threshold ( ) ) )
14391459 } else { None }
14401460 } ) ;
@@ -1446,22 +1466,27 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
14461466 }
14471467
14481468 macro_rules! walk_htlcs {
1449- ( $holder_commitment: expr, $htlc_iter: expr) => {
1469+ ( $holder_commitment: expr, $counterparty_revoked_commitment : expr , $ htlc_iter: expr) => {
14501470 for htlc in $htlc_iter {
14511471 if let Some ( htlc_commitment_tx_output_idx) = htlc. transaction_output_index {
1472+ let mut htlc_spend_txid_opt = None ;
14521473 let mut htlc_update_pending = None ;
14531474 let mut htlc_spend_pending = None ;
14541475 let mut delayed_output_pending = None ;
14551476 for event in us. onchain_events_awaiting_threshold_conf. iter( ) {
14561477 match event. event {
14571478 OnchainEvent :: HTLCUpdate { commitment_tx_output_idx, htlc_value_satoshis, .. }
14581479 if commitment_tx_output_idx == Some ( htlc_commitment_tx_output_idx) => {
1480+ debug_assert!( htlc_spend_txid_opt. is_none( ) ) ;
1481+ htlc_spend_txid_opt = event. transaction. as_ref( ) . map( |tx| tx. txid( ) ) ;
14591482 debug_assert!( htlc_update_pending. is_none( ) ) ;
14601483 debug_assert_eq!( htlc_value_satoshis. unwrap( ) , htlc. amount_msat / 1000 ) ;
14611484 htlc_update_pending = Some ( event. confirmation_threshold( ) ) ;
14621485 } ,
14631486 OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. }
14641487 if commitment_tx_output_idx == htlc_commitment_tx_output_idx => {
1488+ debug_assert!( htlc_spend_txid_opt. is_none( ) ) ;
1489+ htlc_spend_txid_opt = event. transaction. as_ref( ) . map( |tx| tx. txid( ) ) ;
14651490 debug_assert!( htlc_spend_pending. is_none( ) ) ;
14661491 htlc_spend_pending = Some ( ( event. confirmation_threshold( ) , preimage. is_some( ) ) ) ;
14671492 } ,
@@ -1475,22 +1500,69 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
14751500 }
14761501 }
14771502 let htlc_resolved = us. htlcs_resolved_on_chain. iter( )
1478- . find( |v| v. commitment_tx_output_idx == htlc_commitment_tx_output_idx) ;
1503+ . find( |v| if v. commitment_tx_output_idx == htlc_commitment_tx_output_idx {
1504+ debug_assert!( htlc_spend_txid_opt. is_none( ) ) ;
1505+ htlc_spend_txid_opt = v. resolving_txid;
1506+ true
1507+ } else { false } ) ;
14791508 debug_assert!( htlc_update_pending. is_some( ) as u8 + htlc_spend_pending. is_some( ) as u8 + htlc_resolved. is_some( ) as u8 <= 1 ) ;
14801509
1510+ let htlc_output_to_spend =
1511+ if let Some ( txid) = htlc_spend_txid_opt {
1512+ debug_assert!(
1513+ us. onchain_tx_handler. channel_transaction_parameters. opt_anchors. is_none( ) ,
1514+ "This code needs updating for anchors" ) ;
1515+ BitcoinOutPoint :: new( txid, 0 )
1516+ } else {
1517+ BitcoinOutPoint :: new( confirmed_txid. unwrap( ) , htlc_commitment_tx_output_idx)
1518+ } ;
1519+ let htlc_output_needs_spending = us. onchain_tx_handler. is_output_spend_pending( & htlc_output_to_spend) ;
1520+
14811521 if let Some ( conf_thresh) = delayed_output_pending {
14821522 debug_assert!( $holder_commitment) ;
14831523 res. push( Balance :: ClaimableAwaitingConfirmations {
14841524 claimable_amount_satoshis: htlc. amount_msat / 1000 ,
14851525 confirmation_height: conf_thresh,
14861526 } ) ;
1487- } else if htlc_resolved. is_some( ) {
1527+ } else if htlc_resolved. is_some( ) && !htlc_output_needs_spending {
14881528 // Funding transaction spends should be fully confirmed by the time any
14891529 // HTLC transactions are resolved, unless we're talking about a holder
14901530 // commitment tx, whose resolution is delayed until the CSV timeout is
14911531 // reached, even though HTLCs may be resolved after only
14921532 // ANTI_REORG_DELAY confirmations.
14931533 debug_assert!( $holder_commitment || us. funding_spend_confirmed. is_some( ) ) ;
1534+ } else if $counterparty_revoked_commitment {
1535+ let htlc_output_claim_pending = us. onchain_events_awaiting_threshold_conf. iter( ) . find_map( |event| {
1536+ if let OnchainEvent :: MaturingOutput {
1537+ descriptor: SpendableOutputDescriptor :: StaticOutput { .. }
1538+ } = & event. event {
1539+ if event. transaction. as_ref( ) . map( |tx| tx. input. iter( ) . any( |inp| {
1540+ if let Some ( htlc_spend_txid) = htlc_spend_txid_opt {
1541+ Some ( tx. txid( ) ) == htlc_spend_txid_opt ||
1542+ inp. previous_output. txid == htlc_spend_txid
1543+ } else {
1544+ Some ( inp. previous_output. txid) == confirmed_txid &&
1545+ inp. previous_output. vout == htlc_commitment_tx_output_idx
1546+ }
1547+ } ) ) . unwrap_or( false ) {
1548+ Some ( ( ) )
1549+ } else { None }
1550+ } else { None }
1551+ } ) ;
1552+ if htlc_output_claim_pending. is_some( ) {
1553+ // We already push `Balance`s onto the `res` list for every
1554+ // `StaticOutput` in a `MaturingOutput` in the revoked
1555+ // counterparty commitment transaction case generally, so don't
1556+ // need to do so again here.
1557+ } else {
1558+ debug_assert!( htlc_update_pending. is_none( ) ,
1559+ "HTLCUpdate OnchainEvents should never appear for preimage claims" ) ;
1560+ debug_assert!( !htlc. offered || htlc_spend_pending. is_none( ) || !htlc_spend_pending. unwrap( ) . 1 ,
1561+ "We don't (currently) generate preimage claims against revoked outputs, where did you get one?!" ) ;
1562+ res. push( Balance :: CounterpartyRevokedOutputClaimable {
1563+ claimable_amount_satoshis: htlc. amount_msat / 1000 ,
1564+ } ) ;
1565+ }
14941566 } else {
14951567 if htlc. offered == $holder_commitment {
14961568 // If the payment was outbound, check if there's an HTLCUpdate
@@ -1534,8 +1606,8 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
15341606
15351607 if let Some ( txid) = confirmed_txid {
15361608 let mut found_commitment_tx = false ;
1537- if Some ( txid ) == us. current_counterparty_commitment_txid || Some ( txid) == us . prev_counterparty_commitment_txid {
1538- walk_htlcs ! ( false , us . counterparty_claimable_outpoints . get ( & txid ) . unwrap ( ) . iter ( ) . map ( | ( a , _ ) | a ) ) ;
1609+ if let Some ( counterparty_tx_htlcs ) = us. counterparty_claimable_outpoints . get ( & txid) {
1610+ // First look for the to_remote output back to us.
15391611 if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
15401612 if let Some ( value) = us. onchain_events_awaiting_threshold_conf . iter ( ) . find_map ( |event| {
15411613 if let OnchainEvent :: MaturingOutput {
@@ -1554,9 +1626,50 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
15541626 // confirmation with the same height or have never met our dust amount.
15551627 }
15561628 }
1629+ if Some ( txid) == us. current_counterparty_commitment_txid || Some ( txid) == us. prev_counterparty_commitment_txid {
1630+ walk_htlcs ! ( false , false , counterparty_tx_htlcs. iter( ) . map( |( a, _) | a) ) ;
1631+ } else {
1632+ walk_htlcs ! ( false , true , counterparty_tx_htlcs. iter( ) . map( |( a, _) | a) ) ;
1633+ // The counterparty broadcasted a revoked state!
1634+ // Look for any StaticOutputs first, generating claimable balances for those.
1635+ // If any match the confirmed counterparty revoked to_self output, skip
1636+ // generating a CounterpartyRevokedOutputClaimable.
1637+ let mut spent_counterparty_output = false ;
1638+ for event in us. onchain_events_awaiting_threshold_conf . iter ( ) {
1639+ if let OnchainEvent :: MaturingOutput {
1640+ descriptor : SpendableOutputDescriptor :: StaticOutput { output, .. }
1641+ } = & event. event {
1642+ res. push ( Balance :: ClaimableAwaitingConfirmations {
1643+ claimable_amount_satoshis : output. value ,
1644+ confirmation_height : event. confirmation_threshold ( ) ,
1645+ } ) ;
1646+ if let Some ( confirmed_to_self_idx) = confirmed_counterparty_output. map ( |( idx, _) | idx) {
1647+ if event. transaction . as_ref ( ) . map ( |tx|
1648+ tx. input . iter ( ) . any ( |inp| inp. previous_output . vout == confirmed_to_self_idx)
1649+ ) . unwrap_or ( false ) {
1650+ spent_counterparty_output = true ;
1651+ }
1652+ }
1653+ }
1654+ }
1655+
1656+ if spent_counterparty_output {
1657+ } else if let Some ( ( confirmed_to_self_idx, amt) ) = confirmed_counterparty_output {
1658+ let output_spendable = us. onchain_tx_handler
1659+ . is_output_spend_pending ( & BitcoinOutPoint :: new ( txid, confirmed_to_self_idx) ) ;
1660+ if output_spendable {
1661+ res. push ( Balance :: CounterpartyRevokedOutputClaimable {
1662+ claimable_amount_satoshis : amt,
1663+ } ) ;
1664+ }
1665+ } else {
1666+ // Counterparty output is missing, either it was broadcasted on a
1667+ // previous version of LDK or the counterparty hadn't met dust.
1668+ }
1669+ }
15571670 found_commitment_tx = true ;
15581671 } else if txid == us. current_holder_commitment_tx . txid {
1559- walk_htlcs ! ( true , us. current_holder_commitment_tx. htlc_outputs. iter( ) . map( |( a, _, _) | a) ) ;
1672+ walk_htlcs ! ( true , false , us. current_holder_commitment_tx. htlc_outputs. iter( ) . map( |( a, _, _) | a) ) ;
15601673 if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
15611674 res. push ( Balance :: ClaimableAwaitingConfirmations {
15621675 claimable_amount_satoshis : us. current_holder_commitment_tx . to_self_value_sat ,
@@ -1566,7 +1679,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
15661679 found_commitment_tx = true ;
15671680 } else if let Some ( prev_commitment) = & us. prev_holder_signed_commitment_tx {
15681681 if txid == prev_commitment. txid {
1569- walk_htlcs ! ( true , prev_commitment. htlc_outputs. iter( ) . map( |( a, _, _) | a) ) ;
1682+ walk_htlcs ! ( true , false , prev_commitment. htlc_outputs. iter( ) . map( |( a, _, _) | a) ) ;
15701683 if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
15711684 res. push ( Balance :: ClaimableAwaitingConfirmations {
15721685 claimable_amount_satoshis : prev_commitment. to_self_value_sat ,
@@ -1587,8 +1700,6 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
15871700 } ) ;
15881701 }
15891702 }
1590- // TODO: Add logic to provide claimable balances for counterparty broadcasting revoked
1591- // outputs.
15921703 } else {
15931704 let mut claimable_inbound_htlc_value_sat = 0 ;
15941705 for ( htlc, _, _) in us. current_holder_commitment_tx . htlc_outputs . iter ( ) {
0 commit comments