22
22
23
23
use bitcoin:: blockdata:: block:: BlockHeader ;
24
24
use bitcoin:: blockdata:: transaction:: { TxOut , Transaction } ;
25
+ use bitcoin:: blockdata:: transaction:: OutPoint as BitcoinOutPoint ;
25
26
use bitcoin:: blockdata:: script:: { Script , Builder } ;
26
27
use bitcoin:: blockdata:: opcodes;
27
28
@@ -377,6 +378,9 @@ enum OnchainEvent {
377
378
on_local_output_csv : Option < u16 > ,
378
379
/// If the funding spend transaction was a known remote commitment transaction, we track
379
380
/// the output index and amount of the counterparty's `to_self` output here.
381
+ ///
382
+ /// This allows us to generate a [`Balance::CounterpartyRevokedOutputClaimable`] for the
383
+ /// counterparty output.
380
384
commitment_tx_to_counterparty_output : CommitmentTxCounterpartyOutputInfo ,
381
385
} ,
382
386
/// A spend of a commitment transaction HTLC output, set in the cases where *no* `HTLCUpdate`
@@ -577,6 +581,15 @@ pub enum Balance {
577
581
/// done so.
578
582
claimable_height : u32 ,
579
583
} ,
584
+ /// The channel has been closed, and our counterparty broadcasted a revoked commitment
585
+ /// transaction.
586
+ ///
587
+ /// Thus, we're able to claim all outputs in the commitment transaction, one of which has the
588
+ /// following amount.
589
+ CounterpartyRevokedOutputClaimable {
590
+ /// The amount, in satoshis, of the output which we can claim.
591
+ claimable_amount_satoshis : u64 ,
592
+ } ,
580
593
}
581
594
582
595
/// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY.
@@ -1399,9 +1412,9 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1399
1412
/// balance, or until our counterparty has claimed the balance and accrued several
1400
1413
/// confirmations on the claim transaction.
1401
1414
///
1402
- /// Note that the balances available when you or your counterparty have broadcasted revoked
1403
- /// state(s) may not be fully captured here.
1404
- // TODO, fix that ^
1415
+ /// Note that for `ChannelMonitors` which track a channel which went on-chain with versions of
1416
+ /// LDK prior to 0.0.108, balances may not be fully captured if our counterparty broadcasted
1417
+ /// a revoked state.
1405
1418
///
1406
1419
/// See [`Balance`] for additional details on the types of claimable balances which
1407
1420
/// may be returned here and their meanings.
@@ -1410,9 +1423,13 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1410
1423
let us = self . inner . lock ( ) . unwrap ( ) ;
1411
1424
1412
1425
let mut confirmed_txid = us. funding_spend_confirmed ;
1426
+ let mut confirmed_counterparty_output = us. confirmed_commitment_tx_counterparty_output ;
1413
1427
let mut pending_commitment_tx_conf_thresh = None ;
1414
1428
let funding_spend_pending = us. onchain_events_awaiting_threshold_conf . iter ( ) . find_map ( |event| {
1415
- if let OnchainEvent :: FundingSpendConfirmation { .. } = event. event {
1429
+ if let OnchainEvent :: FundingSpendConfirmation { commitment_tx_to_counterparty_output, .. } =
1430
+ event. event
1431
+ {
1432
+ confirmed_counterparty_output = commitment_tx_to_counterparty_output;
1416
1433
Some ( ( event. txid , event. confirmation_threshold ( ) ) )
1417
1434
} else { None }
1418
1435
} ) ;
@@ -1424,22 +1441,25 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1424
1441
}
1425
1442
1426
1443
macro_rules! walk_htlcs {
1427
- ( $holder_commitment: expr, $htlc_iter: expr) => {
1444
+ ( $holder_commitment: expr, $counterparty_revoked_commitment : expr , $ htlc_iter: expr) => {
1428
1445
for htlc in $htlc_iter {
1429
1446
if let Some ( htlc_commitment_tx_output_idx) = htlc. transaction_output_index {
1447
+ let mut htlc_spend_txid_opt = None ;
1430
1448
let mut htlc_update_pending = None ;
1431
1449
let mut htlc_spend_pending = None ;
1432
1450
let mut delayed_output_pending = None ;
1433
1451
for event in us. onchain_events_awaiting_threshold_conf. iter( ) {
1434
1452
match event. event {
1435
1453
OnchainEvent :: HTLCUpdate { commitment_tx_output_idx, htlc_value_satoshis, .. }
1436
1454
if commitment_tx_output_idx == Some ( htlc_commitment_tx_output_idx) => {
1455
+ htlc_spend_txid_opt = event. transaction. as_ref( ) . map( |tx| tx. txid( ) ) ;
1437
1456
debug_assert!( htlc_update_pending. is_none( ) ) ;
1438
1457
debug_assert_eq!( htlc_value_satoshis. unwrap( ) , htlc. amount_msat / 1000 ) ;
1439
1458
htlc_update_pending = Some ( event. confirmation_threshold( ) ) ;
1440
1459
} ,
1441
1460
OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. }
1442
1461
if commitment_tx_output_idx == htlc_commitment_tx_output_idx => {
1462
+ htlc_spend_txid_opt = event. transaction. as_ref( ) . map( |tx| tx. txid( ) ) ;
1443
1463
debug_assert!( htlc_spend_pending. is_none( ) ) ;
1444
1464
htlc_spend_pending = Some ( ( event. confirmation_threshold( ) , preimage. is_some( ) ) ) ;
1445
1465
} ,
@@ -1453,22 +1473,77 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1453
1473
}
1454
1474
}
1455
1475
let htlc_resolved = us. htlcs_resolved_on_chain. iter( )
1456
- . find( |v| v. commitment_tx_output_idx == htlc_commitment_tx_output_idx) ;
1476
+ . find( |v| if v. commitment_tx_output_idx == htlc_commitment_tx_output_idx {
1477
+ debug_assert_ne!( v. resolving_txid, confirmed_txid) ;
1478
+ htlc_spend_txid_opt = v. resolving_txid;
1479
+ true
1480
+ } else { false } ) ;
1457
1481
debug_assert!( htlc_update_pending. is_some( ) as u8 + htlc_spend_pending. is_some( ) as u8 + htlc_resolved. is_some( ) as u8 <= 1 ) ;
1458
1482
1483
+ let htlc_output_needs_spending =
1484
+ us. onchain_tx_handler. is_output_spend_pending( &
1485
+ if let Some ( txid) = htlc_spend_txid_opt {
1486
+ debug_assert!(
1487
+ us. onchain_tx_handler. channel_transaction_parameters. opt_anchors. is_none( ) ,
1488
+ "This code needs updating for anchors" ) ;
1489
+ BitcoinOutPoint :: new( txid, 0 )
1490
+ } else {
1491
+ BitcoinOutPoint :: new( confirmed_txid. unwrap( ) , htlc_commitment_tx_output_idx)
1492
+ } ) ;
1493
+
1459
1494
if let Some ( conf_thresh) = delayed_output_pending {
1460
1495
debug_assert!( $holder_commitment) ;
1461
1496
res. push( Balance :: ClaimableAwaitingConfirmations {
1462
1497
claimable_amount_satoshis: htlc. amount_msat / 1000 ,
1463
1498
confirmation_height: conf_thresh,
1464
1499
} ) ;
1465
- } else if htlc_resolved. is_some( ) {
1500
+ } else if htlc_resolved. is_some( ) && !htlc_output_needs_spending {
1466
1501
// Funding transaction spends should be fully confirmed by the time any
1467
1502
// HTLC transactions are resolved, unless we're talking about a holder
1468
1503
// commitment tx, whose resolution is delayed until the CSV timeout is
1469
1504
// reached, even though HTLCs may be resolved after only
1470
1505
// ANTI_REORG_DELAY confirmations.
1471
1506
debug_assert!( $holder_commitment || us. funding_spend_confirmed. is_some( ) ) ;
1507
+ } else if $counterparty_revoked_commitment {
1508
+ let htlc_output_claim_pending = us. onchain_events_awaiting_threshold_conf. iter( ) . find_map( |event| {
1509
+ if let OnchainEvent :: MaturingOutput {
1510
+ descriptor: SpendableOutputDescriptor :: StaticOutput { .. }
1511
+ } = & event. event {
1512
+ if event. transaction. as_ref( ) . map( |tx| tx. input. iter( ) . any( |inp| {
1513
+ if let Some ( htlc_spend_txid) = htlc_spend_txid_opt {
1514
+ Some ( tx. txid( ) ) == htlc_spend_txid_opt ||
1515
+ inp. previous_output. txid == htlc_spend_txid
1516
+ } else {
1517
+ Some ( inp. previous_output. txid) == confirmed_txid &&
1518
+ inp. previous_output. vout == htlc_commitment_tx_output_idx
1519
+ }
1520
+ } ) ) . unwrap_or( false ) {
1521
+ Some ( ( ) )
1522
+ } else { None }
1523
+ } else { None }
1524
+ } ) ;
1525
+ if htlc_output_claim_pending. is_some( ) {
1526
+ // We already push `Balance`s onto the `res` list for every
1527
+ // `StaticOutput` in a `MaturingOutput` in the revoked
1528
+ // counterparty commitment transaction case generally, so don't
1529
+ // need to do so again here.
1530
+ } else if htlc_spend_pending. is_some( ) {
1531
+ res. push( Balance :: CounterpartyRevokedOutputClaimable {
1532
+ claimable_amount_satoshis: htlc. amount_msat / 1000 ,
1533
+ } ) ;
1534
+ } else if htlc_resolved. is_some( ) {
1535
+ res. push( Balance :: CounterpartyRevokedOutputClaimable {
1536
+ claimable_amount_satoshis: htlc. amount_msat / 1000 ,
1537
+ } ) ;
1538
+ } else {
1539
+ debug_assert!( htlc_update_pending. is_none( ) ,
1540
+ "HTLCUpdate OnchainEvents should never appear for preimage claims" ) ;
1541
+ debug_assert!( htlc_spend_pending. is_none( ) || !htlc_spend_pending. unwrap( ) . 1 ,
1542
+ "We don't (currently) generate preimage claims against revoked outputs, where did you get one?!" ) ;
1543
+ res. push( Balance :: CounterpartyRevokedOutputClaimable {
1544
+ claimable_amount_satoshis: htlc. amount_msat / 1000 ,
1545
+ } ) ;
1546
+ }
1472
1547
} else {
1473
1548
if htlc. offered == $holder_commitment {
1474
1549
// If the payment was outbound, check if there's an HTLCUpdate
@@ -1512,8 +1587,8 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1512
1587
1513
1588
if let Some ( txid) = confirmed_txid {
1514
1589
let mut found_commitment_tx = false ;
1515
- if Some ( txid ) == us. current_counterparty_commitment_txid || Some ( txid) == us . prev_counterparty_commitment_txid {
1516
- walk_htlcs ! ( false , us . counterparty_claimable_outpoints . get ( & txid ) . unwrap ( ) . iter ( ) . map ( | ( a , _ ) | a ) ) ;
1590
+ if let Some ( counterparty_tx_htlcs ) = us. counterparty_claimable_outpoints . get ( & txid) {
1591
+ // First look for the to_remote output back to us.
1517
1592
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
1518
1593
if let Some ( value) = us. onchain_events_awaiting_threshold_conf . iter ( ) . find_map ( |event| {
1519
1594
if let OnchainEvent :: MaturingOutput {
@@ -1532,9 +1607,50 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1532
1607
// confirmation with the same height or have never met our dust amount.
1533
1608
}
1534
1609
}
1610
+ if Some ( txid) == us. current_counterparty_commitment_txid || Some ( txid) == us. prev_counterparty_commitment_txid {
1611
+ walk_htlcs ! ( false , false , counterparty_tx_htlcs. iter( ) . map( |( a, _) | a) ) ;
1612
+ } else {
1613
+ walk_htlcs ! ( false , true , counterparty_tx_htlcs. iter( ) . map( |( a, _) | a) ) ;
1614
+ // The counterparty broadcasted a revoked state!
1615
+ // Look for a StaticOutput spend first, as it should be spending the full set
1616
+ // of commitment transaction outputs, if we see one, assume that it did and
1617
+ // just return that.
1618
+ let mut spent_counterparty_output = false ;
1619
+ for event in us. onchain_events_awaiting_threshold_conf . iter ( ) {
1620
+ if let OnchainEvent :: MaturingOutput {
1621
+ descriptor : SpendableOutputDescriptor :: StaticOutput { output, .. }
1622
+ } = & event. event {
1623
+ res. push ( Balance :: ClaimableAwaitingConfirmations {
1624
+ claimable_amount_satoshis : output. value ,
1625
+ confirmation_height : event. confirmation_threshold ( ) ,
1626
+ } ) ;
1627
+ if let Some ( confirmed_to_self_idx) = confirmed_counterparty_output. map ( |( idx, _) | idx) {
1628
+ if event. transaction . as_ref ( ) . map ( |tx|
1629
+ tx. input . iter ( ) . any ( |inp| inp. previous_output . vout == confirmed_to_self_idx)
1630
+ ) . unwrap_or ( false ) {
1631
+ spent_counterparty_output = true ;
1632
+ }
1633
+ }
1634
+ }
1635
+ }
1636
+
1637
+ if spent_counterparty_output {
1638
+ } else if let Some ( ( confirmed_to_self_idx, amt) ) = confirmed_counterparty_output {
1639
+ let output_spendable = us. onchain_tx_handler
1640
+ . is_output_spend_pending ( & BitcoinOutPoint :: new ( txid, confirmed_to_self_idx) ) ;
1641
+ if output_spendable {
1642
+ res. push ( Balance :: CounterpartyRevokedOutputClaimable {
1643
+ claimable_amount_satoshis : amt,
1644
+ } ) ;
1645
+ }
1646
+ } else {
1647
+ // Counterparty output is missing, either it was broadcasted on a
1648
+ // previous version of LDK or the counterparty hadn't met dust.
1649
+ }
1650
+ }
1535
1651
found_commitment_tx = true ;
1536
1652
} else if txid == us. current_holder_commitment_tx . txid {
1537
- walk_htlcs ! ( true , us. current_holder_commitment_tx. htlc_outputs. iter( ) . map( |( a, _, _) | a) ) ;
1653
+ walk_htlcs ! ( true , false , us. current_holder_commitment_tx. htlc_outputs. iter( ) . map( |( a, _, _) | a) ) ;
1538
1654
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
1539
1655
res. push ( Balance :: ClaimableAwaitingConfirmations {
1540
1656
claimable_amount_satoshis : us. current_holder_commitment_tx . to_self_value_sat ,
@@ -1544,7 +1660,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1544
1660
found_commitment_tx = true ;
1545
1661
} else if let Some ( prev_commitment) = & us. prev_holder_signed_commitment_tx {
1546
1662
if txid == prev_commitment. txid {
1547
- walk_htlcs ! ( true , prev_commitment. htlc_outputs. iter( ) . map( |( a, _, _) | a) ) ;
1663
+ walk_htlcs ! ( true , false , prev_commitment. htlc_outputs. iter( ) . map( |( a, _, _) | a) ) ;
1548
1664
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
1549
1665
res. push ( Balance :: ClaimableAwaitingConfirmations {
1550
1666
claimable_amount_satoshis : prev_commitment. to_self_value_sat ,
@@ -1565,8 +1681,6 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1565
1681
} ) ;
1566
1682
}
1567
1683
}
1568
- // TODO: Add logic to provide claimable balances for counterparty broadcasting revoked
1569
- // outputs.
1570
1684
} else {
1571
1685
let mut claimable_inbound_htlc_value_sat = 0 ;
1572
1686
for ( htlc, _, _) in us. current_holder_commitment_tx . htlc_outputs . iter ( ) {
0 commit comments