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
@@ -588,6 +589,15 @@ pub enum Balance {
588
589
/// done so.
589
590
claimable_height : u32 ,
590
591
} ,
592
+ /// The channel has been closed, and our counterparty broadcasted a revoked commitment
593
+ /// transaction.
594
+ ///
595
+ /// Thus, we're able to claim all outputs in the commitment transaction, one of which has the
596
+ /// following amount.
597
+ CounterpartyRevokedOutputClaimable {
598
+ /// The amount, in satoshis, of the output which we can claim.
599
+ claimable_amount_satoshis : u64 ,
600
+ } ,
591
601
}
592
602
593
603
/// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY.
@@ -1408,9 +1418,9 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1408
1418
/// balance, or until our counterparty has claimed the balance and accrued several
1409
1419
/// confirmations on the claim transaction.
1410
1420
///
1411
- /// Note that the balances available when you or your counterparty have broadcasted revoked
1412
- /// state(s) may not be fully captured here.
1413
- // TODO, fix that ^
1421
+ /// Note that for `ChannelMonitors` which track a channel which went on-chain with versions of
1422
+ /// LDK prior to 0.0.108, balances may not be fully captured if our counterparty broadcasted
1423
+ /// a revoked state.
1414
1424
///
1415
1425
/// See [`Balance`] for additional details on the types of claimable balances which
1416
1426
/// may be returned here and their meanings.
@@ -1419,9 +1429,13 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1419
1429
let us = self . inner . lock ( ) . unwrap ( ) ;
1420
1430
1421
1431
let mut confirmed_txid = us. funding_spend_confirmed ;
1432
+ let mut confirmed_counterparty_output = us. confirmed_commitment_tx_counterparty_output ;
1422
1433
let mut pending_commitment_tx_conf_thresh = None ;
1423
1434
let funding_spend_pending = us. onchain_events_awaiting_threshold_conf . iter ( ) . find_map ( |event| {
1424
- if let OnchainEvent :: FundingSpendConfirmation { .. } = event. event {
1435
+ if let OnchainEvent :: FundingSpendConfirmation { commitment_tx_to_counterparty_output, .. } =
1436
+ event. event
1437
+ {
1438
+ confirmed_counterparty_output = commitment_tx_to_counterparty_output;
1425
1439
Some ( ( event. txid , event. confirmation_threshold ( ) ) )
1426
1440
} else { None }
1427
1441
} ) ;
@@ -1433,9 +1447,10 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1433
1447
}
1434
1448
1435
1449
macro_rules! walk_htlcs {
1436
- ( $holder_commitment: expr, $htlc_iter: expr) => {
1450
+ ( $holder_commitment: expr, $counterparty_revoked_commitment : expr , $ htlc_iter: expr) => {
1437
1451
for htlc in $htlc_iter {
1438
1452
if let Some ( htlc_commitment_tx_output_idx) = htlc. transaction_output_index {
1453
+ let mut htlc_spend_txid_opt = None ;
1439
1454
let mut htlc_update_pending = None ;
1440
1455
let mut htlc_spend_pending = None ;
1441
1456
let mut delayed_output_pending = None ;
@@ -1444,6 +1459,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1444
1459
OnchainEvent :: HTLCUpdate {
1445
1460
commitment_tx_output_idx, onchain_value_satoshis, htlc_value_satoshis, .. }
1446
1461
if commitment_tx_output_idx == Some ( htlc_commitment_tx_output_idx) => {
1462
+ htlc_spend_txid_opt = event. transaction. as_ref( ) . map( |tx| tx. txid( ) ) ;
1447
1463
debug_assert!( htlc_update_pending. is_none( ) ) ;
1448
1464
htlc_update_pending = Some ( (
1449
1465
onchain_value_satoshis. unwrap_or( htlc_value_satoshis. unwrap( ) ) ,
@@ -1452,6 +1468,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1452
1468
OnchainEvent :: HTLCSpendConfirmation {
1453
1469
commitment_tx_output_idx, preimage, onchain_value_satoshis, .. }
1454
1470
if commitment_tx_output_idx == htlc_commitment_tx_output_idx => {
1471
+ htlc_spend_txid_opt = event. transaction. as_ref( ) . map( |tx| tx. txid( ) ) ;
1455
1472
debug_assert!( htlc_spend_pending. is_none( ) ) ;
1456
1473
htlc_spend_pending = Some ( ( event. confirmation_threshold( ) ,
1457
1474
preimage. is_some( ) , onchain_value_satoshis) ) ;
@@ -1466,22 +1483,80 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1466
1483
}
1467
1484
}
1468
1485
let htlc_resolved = us. htlcs_resolved_on_chain. iter( )
1469
- . find( |v| v. commitment_tx_output_idx == htlc_commitment_tx_output_idx) ;
1486
+ . find( |v| if v. commitment_tx_output_idx == htlc_commitment_tx_output_idx {
1487
+ if v. resolving_txid != confirmed_txid {
1488
+ htlc_spend_txid_opt = v. resolving_txid;
1489
+ }
1490
+ true
1491
+ } else { false } ) ;
1470
1492
debug_assert!( htlc_update_pending. is_some( ) as u8 + htlc_spend_pending. is_some( ) as u8 + htlc_resolved. is_some( ) as u8 <= 1 ) ;
1471
1493
1494
+ let htlc_output_needs_spending =
1495
+ us. onchain_tx_handler. is_output_spend_pending( &
1496
+ if let Some ( txid) = htlc_spend_txid_opt {
1497
+ debug_assert!(
1498
+ us. onchain_tx_handler. channel_transaction_parameters. opt_anchors. is_none( ) ,
1499
+ "This code needs updating for anchors" ) ;
1500
+ BitcoinOutPoint :: new( txid, 0 )
1501
+ } else {
1502
+ BitcoinOutPoint :: new( confirmed_txid. unwrap( ) , htlc_commitment_tx_output_idx)
1503
+ } ) ;
1504
+
1472
1505
if let Some ( conf_thresh) = delayed_output_pending {
1473
1506
debug_assert!( $holder_commitment) ;
1474
1507
res. push( Balance :: ClaimableAwaitingConfirmations {
1475
1508
claimable_amount_satoshis: htlc. amount_msat / 1000 ,
1476
1509
confirmation_height: conf_thresh,
1477
1510
} ) ;
1478
- } else if htlc_resolved. is_some( ) {
1511
+ } else if htlc_resolved. is_some( ) && !htlc_output_needs_spending {
1479
1512
// Funding transaction spends should be fully confirmed by the time any
1480
1513
// HTLC transactions are resolved, unless we're talking about a holder
1481
1514
// commitment tx, whose resolution is delayed until the CSV timeout is
1482
1515
// reached, even though HTLCs may be resolved after only
1483
1516
// ANTI_REORG_DELAY confirmations.
1484
1517
debug_assert!( $holder_commitment || us. funding_spend_confirmed. is_some( ) ) ;
1518
+ } else if $counterparty_revoked_commitment {
1519
+ let htlc_output_claim_pending = us. onchain_events_awaiting_threshold_conf. iter( ) . find_map( |event| {
1520
+ if let OnchainEvent :: MaturingOutput {
1521
+ descriptor: SpendableOutputDescriptor :: StaticOutput { .. }
1522
+ } = & event. event {
1523
+ if event. transaction. as_ref( ) . map( |tx| tx. input. iter( ) . any( |inp| {
1524
+ if let Some ( htlc_spend_txid) = htlc_spend_txid_opt {
1525
+ Some ( tx. txid( ) ) == htlc_spend_txid_opt || // XXX uneccessary?
1526
+ inp. previous_output. txid == htlc_spend_txid
1527
+ } else {
1528
+ Some ( inp. previous_output. txid) == confirmed_txid &&
1529
+ inp. previous_output. vout == htlc_commitment_tx_output_idx
1530
+ }
1531
+ } ) ) . unwrap_or( false ) {
1532
+ Some ( ( ) )
1533
+ } else { None }
1534
+ } else { None }
1535
+ } ) ;
1536
+ if htlc_output_claim_pending. is_some( ) {
1537
+ // We already push `Balance`s onto the `res` list for every
1538
+ // `StaticOutput` in a `MaturingOutput` in the revoked
1539
+ // counterparty commitment transaction case generally, so don't
1540
+ // need to do so again here.
1541
+ } else if let Some ( ( _, _, amount_sats_option) ) = htlc_spend_pending {
1542
+ if let Some ( amount_sats) = amount_sats_option {
1543
+ res. push( Balance :: CounterpartyRevokedOutputClaimable {
1544
+ claimable_amount_satoshis: amount_sats,
1545
+ } ) ;
1546
+ }
1547
+ } else if let Some ( Some ( val) ) = htlc_resolved. map( |v| v. onchain_value_satoshis) {
1548
+ res. push( Balance :: CounterpartyRevokedOutputClaimable {
1549
+ claimable_amount_satoshis: val,
1550
+ } ) ;
1551
+ } else {
1552
+ debug_assert!( htlc_update_pending. is_none( ) ,
1553
+ "HTLCUpdate OnchainEvents should never appear for preimage claims" ) ;
1554
+ debug_assert!( htlc_spend_pending. is_none( ) || !htlc_spend_pending. unwrap( ) . 1 ,
1555
+ "We don't (currently) generate preimage claims against revoked outputs, where did you get one?!" ) ;
1556
+ res. push( Balance :: CounterpartyRevokedOutputClaimable {
1557
+ claimable_amount_satoshis: htlc. amount_msat / 1000 ,
1558
+ } ) ;
1559
+ }
1485
1560
} else {
1486
1561
if htlc. offered == $holder_commitment {
1487
1562
// If the payment was outbound, check if there's an HTLCUpdate
@@ -1525,8 +1600,8 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1525
1600
1526
1601
if let Some ( txid) = confirmed_txid {
1527
1602
let mut found_commitment_tx = false ;
1528
- if Some ( txid ) == us. current_counterparty_commitment_txid || Some ( txid) == us . prev_counterparty_commitment_txid {
1529
- walk_htlcs ! ( false , us . counterparty_claimable_outpoints . get ( & txid ) . unwrap ( ) . iter ( ) . map ( | ( a , _ ) | a ) ) ;
1603
+ if let Some ( counterparty_tx_htlcs ) = us. counterparty_claimable_outpoints . get ( & txid) {
1604
+ // First look for the to_remote output back to us.
1530
1605
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
1531
1606
if let Some ( value) = us. onchain_events_awaiting_threshold_conf . iter ( ) . find_map ( |event| {
1532
1607
if let OnchainEvent :: MaturingOutput {
@@ -1545,9 +1620,53 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1545
1620
// confirmation with the same height or have never met our dust amount.
1546
1621
}
1547
1622
}
1623
+ if Some ( txid) == us. current_counterparty_commitment_txid || Some ( txid) == us. prev_counterparty_commitment_txid {
1624
+ walk_htlcs ! ( false , false , counterparty_tx_htlcs. iter( ) . map( |( a, _) | a) ) ;
1625
+ } else {
1626
+ walk_htlcs ! ( true , true , counterparty_tx_htlcs. iter( ) . map( |( a, _) | a) ) ;
1627
+ // The counterparty broadcasted a revoked state!
1628
+ // Look for a StaticOutput spend first, as it should be spending the full set
1629
+ // of commitment transaction outputs, if we see one, assume that it did and
1630
+ // just return that.
1631
+ let mut spent_counterparty_output = false ;
1632
+ for event in us. onchain_events_awaiting_threshold_conf . iter ( ) {
1633
+ if let OnchainEvent :: MaturingOutput {
1634
+ descriptor : SpendableOutputDescriptor :: StaticOutput { output, .. }
1635
+ } = & event. event {
1636
+ res. push ( Balance :: ClaimableAwaitingConfirmations {
1637
+ claimable_amount_satoshis : output. value ,
1638
+ confirmation_height : event. confirmation_threshold ( ) ,
1639
+ } ) ;
1640
+ if let Some ( confirmed_to_self_idx) = confirmed_counterparty_output. map ( |( idx, _) | idx) {
1641
+ if event. transaction . as_ref ( ) . map ( |tx|
1642
+ tx. input . iter ( ) . any ( |inp| inp. previous_output . vout == confirmed_to_self_idx)
1643
+ ) . unwrap_or ( false ) {
1644
+ spent_counterparty_output = true ;
1645
+ }
1646
+ }
1647
+ }
1648
+ }
1649
+
1650
+ if spent_counterparty_output {
1651
+ } else if let Some ( ( _, amt) ) = confirmed_counterparty_output {
1652
+ debug_assert ! ( confirmed_counterparty_output. is_some( ) ) ;
1653
+ if let Some ( confirmed_to_self_idx) = confirmed_counterparty_output. map ( |( idx, _) | idx) {
1654
+ let output_spendable = us. onchain_tx_handler
1655
+ . is_output_spend_pending ( & BitcoinOutPoint :: new ( txid, confirmed_to_self_idx) ) ;
1656
+ if output_spendable {
1657
+ res. push ( Balance :: CounterpartyRevokedOutputClaimable {
1658
+ claimable_amount_satoshis : amt,
1659
+ } ) ;
1660
+ }
1661
+ }
1662
+ } else {
1663
+ // Counterparty output is missing, either it was broadcasted on a
1664
+ // previous version of LDK or the counterparty hadn't met dust.
1665
+ }
1666
+ }
1548
1667
found_commitment_tx = true ;
1549
1668
} else if txid == us. current_holder_commitment_tx . txid {
1550
- walk_htlcs ! ( true , us. current_holder_commitment_tx. htlc_outputs. iter( ) . map( |( a, _, _) | a) ) ;
1669
+ walk_htlcs ! ( true , false , us. current_holder_commitment_tx. htlc_outputs. iter( ) . map( |( a, _, _) | a) ) ;
1551
1670
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
1552
1671
res. push ( Balance :: ClaimableAwaitingConfirmations {
1553
1672
claimable_amount_satoshis : us. current_holder_commitment_tx . to_self_value_sat ,
@@ -1557,7 +1676,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1557
1676
found_commitment_tx = true ;
1558
1677
} else if let Some ( prev_commitment) = & us. prev_holder_signed_commitment_tx {
1559
1678
if txid == prev_commitment. txid {
1560
- walk_htlcs ! ( true , prev_commitment. htlc_outputs. iter( ) . map( |( a, _, _) | a) ) ;
1679
+ walk_htlcs ! ( true , false , prev_commitment. htlc_outputs. iter( ) . map( |( a, _, _) | a) ) ;
1561
1680
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
1562
1681
res. push ( Balance :: ClaimableAwaitingConfirmations {
1563
1682
claimable_amount_satoshis : prev_commitment. to_self_value_sat ,
@@ -1578,8 +1697,6 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1578
1697
} ) ;
1579
1698
}
1580
1699
}
1581
- // TODO: Add logic to provide claimable balances for counterparty broadcasting revoked
1582
- // outputs.
1583
1700
} else {
1584
1701
let mut claimable_inbound_htlc_value_sat = 0 ;
1585
1702
for ( htlc, _, _) in us. current_holder_commitment_tx . htlc_outputs . iter ( ) {
0 commit comments