@@ -1427,7 +1427,150 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
14271427 pub fn current_best_block ( & self ) -> BestBlock {
14281428 self . inner . lock ( ) . unwrap ( ) . best_block . clone ( )
14291429 }
1430+ }
1431+
1432+ impl < Signer : Sign > ChannelMonitorImpl < Signer > {
1433+ /// Helper for get_claimable_balances which does the work for an individual HTLC, generating up
1434+ /// to one `Balance` for the HTLC.
1435+ fn get_htlc_balance ( & self , htlc : & HTLCOutputInCommitment , holder_commitment : bool ,
1436+ counterparty_revoked_commitment : bool , confirmed_txid : Option < Txid > )
1437+ -> Option < Balance > {
1438+ let htlc_commitment_tx_output_idx =
1439+ if let Some ( v) = htlc. transaction_output_index { v } else { return None ; } ;
1440+
1441+ let mut htlc_spend_txid_opt = None ;
1442+ let mut holder_timeout_spend_pending = None ;
1443+ let mut htlc_spend_pending = None ;
1444+ let mut holder_delayed_output_pending = None ;
1445+ for event in self . onchain_events_awaiting_threshold_conf . iter ( ) {
1446+ match event. event {
1447+ OnchainEvent :: HTLCUpdate { commitment_tx_output_idx, htlc_value_satoshis, .. }
1448+ if commitment_tx_output_idx == Some ( htlc_commitment_tx_output_idx) => {
1449+ debug_assert ! ( htlc_spend_txid_opt. is_none( ) ) ;
1450+ htlc_spend_txid_opt = event. transaction . as_ref ( ) . map ( |tx| tx. txid ( ) ) ;
1451+ debug_assert ! ( holder_timeout_spend_pending. is_none( ) ) ;
1452+ debug_assert_eq ! ( htlc_value_satoshis. unwrap( ) , htlc. amount_msat / 1000 ) ;
1453+ holder_timeout_spend_pending = Some ( event. confirmation_threshold ( ) ) ;
1454+ } ,
1455+ OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. }
1456+ if commitment_tx_output_idx == htlc_commitment_tx_output_idx => {
1457+ debug_assert ! ( htlc_spend_txid_opt. is_none( ) ) ;
1458+ htlc_spend_txid_opt = event. transaction . as_ref ( ) . map ( |tx| tx. txid ( ) ) ;
1459+ debug_assert ! ( htlc_spend_pending. is_none( ) ) ;
1460+ htlc_spend_pending = Some ( ( event. confirmation_threshold ( ) , preimage. is_some ( ) ) ) ;
1461+ } ,
1462+ OnchainEvent :: MaturingOutput {
1463+ descriptor : SpendableOutputDescriptor :: DelayedPaymentOutput ( ref descriptor) }
1464+ if descriptor. outpoint . index as u32 == htlc_commitment_tx_output_idx => {
1465+ debug_assert ! ( holder_delayed_output_pending. is_none( ) ) ;
1466+ holder_delayed_output_pending = Some ( event. confirmation_threshold ( ) ) ;
1467+ } ,
1468+ _ => { } ,
1469+ }
1470+ }
1471+ let htlc_resolved = self . htlcs_resolved_on_chain . iter ( )
1472+ . find ( |v| if v. commitment_tx_output_idx == htlc_commitment_tx_output_idx {
1473+ debug_assert ! ( htlc_spend_txid_opt. is_none( ) ) ;
1474+ htlc_spend_txid_opt = v. resolving_txid ;
1475+ true
1476+ } else { false } ) ;
1477+ debug_assert ! ( holder_timeout_spend_pending. is_some( ) as u8 + htlc_spend_pending. is_some( ) as u8 + htlc_resolved. is_some( ) as u8 <= 1 ) ;
1478+
1479+ let htlc_output_to_spend =
1480+ if let Some ( txid) = htlc_spend_txid_opt {
1481+ debug_assert ! (
1482+ self . onchain_tx_handler. channel_transaction_parameters. opt_anchors. is_none( ) ,
1483+ "This code needs updating for anchors" ) ;
1484+ BitcoinOutPoint :: new ( txid, 0 )
1485+ } else {
1486+ BitcoinOutPoint :: new ( confirmed_txid. unwrap ( ) , htlc_commitment_tx_output_idx)
1487+ } ;
1488+ let htlc_output_spend_pending = self . onchain_tx_handler . is_output_spend_pending ( & htlc_output_to_spend) ;
14301489
1490+ if let Some ( conf_thresh) = holder_delayed_output_pending {
1491+ debug_assert ! ( holder_commitment) ;
1492+ return Some ( Balance :: ClaimableAwaitingConfirmations {
1493+ claimable_amount_satoshis : htlc. amount_msat / 1000 ,
1494+ confirmation_height : conf_thresh,
1495+ } ) ;
1496+ } else if htlc_resolved. is_some ( ) && !htlc_output_spend_pending {
1497+ // Funding transaction spends should be fully confirmed by the time any
1498+ // HTLC transactions are resolved, unless we're talking about a holder
1499+ // commitment tx, whose resolution is delayed until the CSV timeout is
1500+ // reached, even though HTLCs may be resolved after only
1501+ // ANTI_REORG_DELAY confirmations.
1502+ debug_assert ! ( holder_commitment || self . funding_spend_confirmed. is_some( ) ) ;
1503+ } else if counterparty_revoked_commitment {
1504+ let htlc_output_claim_pending = self . onchain_events_awaiting_threshold_conf . iter ( ) . find_map ( |event| {
1505+ if let OnchainEvent :: MaturingOutput {
1506+ descriptor : SpendableOutputDescriptor :: StaticOutput { .. }
1507+ } = & event. event {
1508+ if event. transaction . as_ref ( ) . map ( |tx| tx. input . iter ( ) . any ( |inp| {
1509+ if let Some ( htlc_spend_txid) = htlc_spend_txid_opt {
1510+ Some ( tx. txid ( ) ) == htlc_spend_txid_opt ||
1511+ inp. previous_output . txid == htlc_spend_txid
1512+ } else {
1513+ Some ( inp. previous_output . txid ) == confirmed_txid &&
1514+ inp. previous_output . vout == htlc_commitment_tx_output_idx
1515+ }
1516+ } ) ) . unwrap_or ( false ) {
1517+ Some ( ( ) )
1518+ } else { None }
1519+ } else { None }
1520+ } ) ;
1521+ if htlc_output_claim_pending. is_some ( ) {
1522+ // We already push `Balance`s onto the `res` list for every
1523+ // `StaticOutput` in a `MaturingOutput` in the revoked
1524+ // counterparty commitment transaction case generally, so don't
1525+ // need to do so again here.
1526+ } else {
1527+ debug_assert ! ( holder_timeout_spend_pending. is_none( ) ,
1528+ "HTLCUpdate OnchainEvents should never appear for preimage claims" ) ;
1529+ debug_assert ! ( !htlc. offered || htlc_spend_pending. is_none( ) || !htlc_spend_pending. unwrap( ) . 1 ,
1530+ "We don't (currently) generate preimage claims against revoked outputs, where did you get one?!" ) ;
1531+ return Some ( Balance :: CounterpartyRevokedOutputClaimable {
1532+ claimable_amount_satoshis : htlc. amount_msat / 1000 ,
1533+ } ) ;
1534+ }
1535+ } else if htlc. offered == holder_commitment {
1536+ // If the payment was outbound, check if there's an HTLCUpdate
1537+ // indicating we have spent this HTLC with a timeout, claiming it back
1538+ // and awaiting confirmations on it.
1539+ if let Some ( conf_thresh) = holder_timeout_spend_pending {
1540+ return Some ( Balance :: ClaimableAwaitingConfirmations {
1541+ claimable_amount_satoshis : htlc. amount_msat / 1000 ,
1542+ confirmation_height : conf_thresh,
1543+ } ) ;
1544+ } else {
1545+ return Some ( Balance :: MaybeClaimableHTLCAwaitingTimeout {
1546+ claimable_amount_satoshis : htlc. amount_msat / 1000 ,
1547+ claimable_height : htlc. cltv_expiry ,
1548+ } ) ;
1549+ }
1550+ } else if self . payment_preimages . get ( & htlc. payment_hash ) . is_some ( ) {
1551+ // Otherwise (the payment was inbound), only expose it as claimable if
1552+ // we know the preimage.
1553+ // Note that if there is a pending claim, but it did not use the
1554+ // preimage, we lost funds to our counterparty! We will then continue
1555+ // to show it as ContentiousClaimable until ANTI_REORG_DELAY.
1556+ debug_assert ! ( holder_timeout_spend_pending. is_none( ) ) ;
1557+ if let Some ( ( conf_thresh, true ) ) = htlc_spend_pending {
1558+ return Some ( Balance :: ClaimableAwaitingConfirmations {
1559+ claimable_amount_satoshis : htlc. amount_msat / 1000 ,
1560+ confirmation_height : conf_thresh,
1561+ } ) ;
1562+ } else {
1563+ return Some ( Balance :: ContentiousClaimable {
1564+ claimable_amount_satoshis : htlc. amount_msat / 1000 ,
1565+ timeout_height : htlc. cltv_expiry ,
1566+ } ) ;
1567+ }
1568+ }
1569+ None
1570+ }
1571+ }
1572+
1573+ impl < Signer : Sign > ChannelMonitor < Signer > {
14311574 /// Gets the balances in this channel which are either claimable by us if we were to
14321575 /// force-close the channel now or which are claimable on-chain (possibly awaiting
14331576 /// confirmation).
@@ -1468,136 +1611,10 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
14681611 macro_rules! walk_htlcs {
14691612 ( $holder_commitment: expr, $counterparty_revoked_commitment: expr, $htlc_iter: expr) => {
14701613 for htlc in $htlc_iter {
1471- if let Some ( htlc_commitment_tx_output_idx) = htlc. transaction_output_index {
1472- let mut htlc_spend_txid_opt = None ;
1473- let mut htlc_update_pending = None ;
1474- let mut htlc_spend_pending = None ;
1475- let mut delayed_output_pending = None ;
1476- for event in us. onchain_events_awaiting_threshold_conf. iter( ) {
1477- match event. event {
1478- OnchainEvent :: HTLCUpdate { commitment_tx_output_idx, htlc_value_satoshis, .. }
1479- 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( ) ) ;
1482- debug_assert!( htlc_update_pending. is_none( ) ) ;
1483- debug_assert_eq!( htlc_value_satoshis. unwrap( ) , htlc. amount_msat / 1000 ) ;
1484- htlc_update_pending = Some ( event. confirmation_threshold( ) ) ;
1485- } ,
1486- OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. }
1487- 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( ) ) ;
1490- debug_assert!( htlc_spend_pending. is_none( ) ) ;
1491- htlc_spend_pending = Some ( ( event. confirmation_threshold( ) , preimage. is_some( ) ) ) ;
1492- } ,
1493- OnchainEvent :: MaturingOutput {
1494- descriptor: SpendableOutputDescriptor :: DelayedPaymentOutput ( ref descriptor) }
1495- if descriptor. outpoint. index as u32 == htlc_commitment_tx_output_idx => {
1496- debug_assert!( delayed_output_pending. is_none( ) ) ;
1497- delayed_output_pending = Some ( event. confirmation_threshold( ) ) ;
1498- } ,
1499- _ => { } ,
1500- }
1501- }
1502- let htlc_resolved = us. htlcs_resolved_on_chain. iter( )
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 } ) ;
1508- debug_assert!( htlc_update_pending. is_some( ) as u8 + htlc_spend_pending. is_some( ) as u8 + htlc_resolved. is_some( ) as u8 <= 1 ) ;
1509-
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) ;
1614+ if htlc. transaction_output_index. is_some( ) {
15201615
1521- if let Some ( conf_thresh) = delayed_output_pending {
1522- debug_assert!( $holder_commitment) ;
1523- res. push( Balance :: ClaimableAwaitingConfirmations {
1524- claimable_amount_satoshis: htlc. amount_msat / 1000 ,
1525- confirmation_height: conf_thresh,
1526- } ) ;
1527- } else if htlc_resolved. is_some( ) && !htlc_output_needs_spending {
1528- // Funding transaction spends should be fully confirmed by the time any
1529- // HTLC transactions are resolved, unless we're talking about a holder
1530- // commitment tx, whose resolution is delayed until the CSV timeout is
1531- // reached, even though HTLCs may be resolved after only
1532- // ANTI_REORG_DELAY confirmations.
1533- 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- }
1566- } else {
1567- if htlc. offered == $holder_commitment {
1568- // If the payment was outbound, check if there's an HTLCUpdate
1569- // indicating we have spent this HTLC with a timeout, claiming it back
1570- // and awaiting confirmations on it.
1571- if let Some ( conf_thresh) = htlc_update_pending {
1572- res. push( Balance :: ClaimableAwaitingConfirmations {
1573- claimable_amount_satoshis: htlc. amount_msat / 1000 ,
1574- confirmation_height: conf_thresh,
1575- } ) ;
1576- } else {
1577- res. push( Balance :: MaybeClaimableHTLCAwaitingTimeout {
1578- claimable_amount_satoshis: htlc. amount_msat / 1000 ,
1579- claimable_height: htlc. cltv_expiry,
1580- } ) ;
1581- }
1582- } else if us. payment_preimages. get( & htlc. payment_hash) . is_some( ) {
1583- // Otherwise (the payment was inbound), only expose it as claimable if
1584- // we know the preimage.
1585- // Note that if there is a pending claim, but it did not use the
1586- // preimage, we lost funds to our counterparty! We will then continue
1587- // to show it as ContentiousClaimable until ANTI_REORG_DELAY.
1588- debug_assert!( htlc_update_pending. is_none( ) ) ;
1589- if let Some ( ( conf_thresh, true ) ) = htlc_spend_pending {
1590- res. push( Balance :: ClaimableAwaitingConfirmations {
1591- claimable_amount_satoshis: htlc. amount_msat / 1000 ,
1592- confirmation_height: conf_thresh,
1593- } ) ;
1594- } else {
1595- res. push( Balance :: ContentiousClaimable {
1596- claimable_amount_satoshis: htlc. amount_msat / 1000 ,
1597- timeout_height: htlc. cltv_expiry,
1598- } ) ;
1599- }
1600- }
1616+ if let Some ( bal) = us. get_htlc_balance( htlc, $holder_commitment, $counterparty_revoked_commitment, confirmed_txid) {
1617+ res. push( bal) ;
16011618 }
16021619 }
16031620 }
0 commit comments