@@ -53,7 +53,7 @@ use crate::util::ser::{Readable, ReadableArgs, MaybeReadable, Writer, Writeable,
53
53
use crate :: util:: byte_utils;
54
54
use crate :: util:: events:: Event ;
55
55
#[ cfg( anchors) ]
56
- use crate :: util:: events:: { AnchorDescriptor , BumpTransactionEvent } ;
56
+ use crate :: util:: events:: { AnchorDescriptor , HTLCDescriptor , BumpTransactionEvent } ;
57
57
58
58
use crate :: prelude:: * ;
59
59
use core:: { cmp, mem} ;
@@ -647,6 +647,7 @@ struct IrrevocablyResolvedHTLC {
647
647
/// was not present in the confirmed commitment transaction), HTLC-Success, or HTLC-Timeout
648
648
/// transaction.
649
649
resolving_txid : Option < Txid > , // Added as optional, but always filled in, in 0.0.110
650
+ resolving_tx : Option < Transaction > ,
650
651
/// Only set if the HTLC claim was ours using a payment preimage
651
652
payment_preimage : Option < PaymentPreimage > ,
652
653
}
@@ -662,6 +663,7 @@ impl Writeable for IrrevocablyResolvedHTLC {
662
663
( 0 , mapped_commitment_tx_output_idx, required) ,
663
664
( 1 , self . resolving_txid, option) ,
664
665
( 2 , self . payment_preimage, option) ,
666
+ ( 3 , self . resolving_tx, option) ,
665
667
} ) ;
666
668
Ok ( ( ) )
667
669
}
@@ -672,15 +674,18 @@ impl Readable for IrrevocablyResolvedHTLC {
672
674
let mut mapped_commitment_tx_output_idx = 0 ;
673
675
let mut resolving_txid = None ;
674
676
let mut payment_preimage = None ;
677
+ let mut resolving_tx = None ;
675
678
read_tlv_fields ! ( reader, {
676
679
( 0 , mapped_commitment_tx_output_idx, required) ,
677
680
( 1 , resolving_txid, option) ,
678
681
( 2 , payment_preimage, option) ,
682
+ ( 3 , resolving_tx, option) ,
679
683
} ) ;
680
684
Ok ( Self {
681
685
commitment_tx_output_idx : if mapped_commitment_tx_output_idx == u32:: max_value ( ) { None } else { Some ( mapped_commitment_tx_output_idx) } ,
682
686
resolving_txid,
683
687
payment_preimage,
688
+ resolving_tx,
684
689
} )
685
690
}
686
691
}
@@ -1526,6 +1531,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
1526
1531
if let Some ( v) = htlc. transaction_output_index { v } else { return None ; } ;
1527
1532
1528
1533
let mut htlc_spend_txid_opt = None ;
1534
+ let mut htlc_spend_tx_opt = None ;
1529
1535
let mut holder_timeout_spend_pending = None ;
1530
1536
let mut htlc_spend_pending = None ;
1531
1537
let mut holder_delayed_output_pending = None ;
@@ -1534,15 +1540,19 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
1534
1540
OnchainEvent :: HTLCUpdate { commitment_tx_output_idx, htlc_value_satoshis, .. }
1535
1541
if commitment_tx_output_idx == Some ( htlc_commitment_tx_output_idx) => {
1536
1542
debug_assert ! ( htlc_spend_txid_opt. is_none( ) ) ;
1537
- htlc_spend_txid_opt = event. transaction . as_ref ( ) . map ( |tx| tx. txid ( ) ) ;
1543
+ htlc_spend_txid_opt = Some ( & event. txid ) ;
1544
+ debug_assert ! ( htlc_spend_tx_opt. is_none( ) ) ;
1545
+ htlc_spend_tx_opt = event. transaction . as_ref ( ) ;
1538
1546
debug_assert ! ( holder_timeout_spend_pending. is_none( ) ) ;
1539
1547
debug_assert_eq ! ( htlc_value_satoshis. unwrap( ) , htlc. amount_msat / 1000 ) ;
1540
1548
holder_timeout_spend_pending = Some ( event. confirmation_threshold ( ) ) ;
1541
1549
} ,
1542
1550
OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. }
1543
1551
if commitment_tx_output_idx == htlc_commitment_tx_output_idx => {
1544
1552
debug_assert ! ( htlc_spend_txid_opt. is_none( ) ) ;
1545
- htlc_spend_txid_opt = event. transaction . as_ref ( ) . map ( |tx| tx. txid ( ) ) ;
1553
+ htlc_spend_txid_opt = Some ( & event. txid ) ;
1554
+ debug_assert ! ( htlc_spend_tx_opt. is_none( ) ) ;
1555
+ htlc_spend_tx_opt = event. transaction . as_ref ( ) ;
1546
1556
debug_assert ! ( htlc_spend_pending. is_none( ) ) ;
1547
1557
htlc_spend_pending = Some ( ( event. confirmation_threshold ( ) , preimage. is_some ( ) ) ) ;
1548
1558
} ,
@@ -1558,19 +1568,32 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
1558
1568
let htlc_resolved = self . htlcs_resolved_on_chain . iter ( )
1559
1569
. find ( |v| if v. commitment_tx_output_idx == Some ( htlc_commitment_tx_output_idx) {
1560
1570
debug_assert ! ( htlc_spend_txid_opt. is_none( ) ) ;
1561
- htlc_spend_txid_opt = v. resolving_txid ;
1571
+ htlc_spend_txid_opt = v. resolving_txid . as_ref ( ) ;
1572
+ debug_assert ! ( htlc_spend_tx_opt. is_none( ) ) ;
1573
+ htlc_spend_tx_opt = v. resolving_tx . as_ref ( ) ;
1562
1574
true
1563
1575
} else { false } ) ;
1564
1576
debug_assert ! ( holder_timeout_spend_pending. is_some( ) as u8 + htlc_spend_pending. is_some( ) as u8 + htlc_resolved. is_some( ) as u8 <= 1 ) ;
1565
1577
1578
+ let htlc_commitment_outpoint = BitcoinOutPoint :: new ( confirmed_txid. unwrap ( ) , htlc_commitment_tx_output_idx) ;
1566
1579
let htlc_output_to_spend =
1567
1580
if let Some ( txid) = htlc_spend_txid_opt {
1568
- debug_assert ! (
1569
- self . onchain_tx_handler. channel_transaction_parameters. opt_anchors. is_none( ) ,
1570
- "This code needs updating for anchors" ) ;
1571
- BitcoinOutPoint :: new ( txid, 0 )
1581
+ // Because HTLC transactions either only have 1 input and 1 output (pre-anchors) or
1582
+ // are signed with SIGHASH_SINGLE|ANYONECANPAY under BIP-0143 (post-anchors), we can
1583
+ // locate the correct output by ensuring its adjacent input spends the HTLC output
1584
+ // in the commitment.
1585
+ if let Some ( ref tx) = htlc_spend_tx_opt {
1586
+ let htlc_input_idx_opt = tx. input . iter ( ) . enumerate ( )
1587
+ . find ( |( _, input) | input. previous_output == htlc_commitment_outpoint)
1588
+ . map ( |( idx, _) | idx as u32 ) ;
1589
+ debug_assert ! ( htlc_input_idx_opt. is_some( ) ) ;
1590
+ BitcoinOutPoint :: new ( * txid, htlc_input_idx_opt. unwrap_or ( 0 ) )
1591
+ } else {
1592
+ debug_assert ! ( !self . onchain_tx_handler. opt_anchors( ) ) ;
1593
+ BitcoinOutPoint :: new ( * txid, 0 )
1594
+ }
1572
1595
} else {
1573
- BitcoinOutPoint :: new ( confirmed_txid . unwrap ( ) , htlc_commitment_tx_output_idx )
1596
+ htlc_commitment_outpoint
1574
1597
} ;
1575
1598
let htlc_output_spend_pending = self . onchain_tx_handler . is_output_spend_pending ( & htlc_output_to_spend) ;
1576
1599
@@ -1594,8 +1617,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
1594
1617
} = & event. event {
1595
1618
if event. transaction . as_ref ( ) . map ( |tx| tx. input . iter ( ) . any ( |inp| {
1596
1619
if let Some ( htlc_spend_txid) = htlc_spend_txid_opt {
1597
- Some ( tx. txid ( ) ) == htlc_spend_txid_opt ||
1598
- inp. previous_output . txid == htlc_spend_txid
1620
+ tx. txid ( ) == * htlc_spend_txid || inp. previous_output . txid == * htlc_spend_txid
1599
1621
} else {
1600
1622
Some ( inp. previous_output . txid ) == confirmed_txid &&
1601
1623
inp. previous_output . vout == htlc_commitment_tx_output_idx
@@ -2403,6 +2425,27 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2403
2425
pending_htlcs,
2404
2426
} ) ) ;
2405
2427
} ,
2428
+ ClaimEvent :: BumpHTLC {
2429
+ target_feerate_sat_per_1000_weight, htlcs,
2430
+ } => {
2431
+ let mut htlc_descriptors = Vec :: with_capacity ( htlcs. len ( ) ) ;
2432
+ for htlc in htlcs {
2433
+ htlc_descriptors. push ( HTLCDescriptor {
2434
+ channel_keys_id : self . channel_keys_id ,
2435
+ channel_value_satoshis : self . channel_value_satoshis ,
2436
+ channel_parameters : self . onchain_tx_handler . channel_transaction_parameters . clone ( ) ,
2437
+ commitment_txid : htlc. commitment_txid ,
2438
+ per_commitment_number : htlc. per_commitment_number ,
2439
+ htlc : htlc. htlc ,
2440
+ preimage : htlc. preimage ,
2441
+ counterparty_sig : htlc. counterparty_sig ,
2442
+ } ) ;
2443
+ }
2444
+ ret. push ( Event :: BumpTransaction ( BumpTransactionEvent :: HTLCResolution {
2445
+ target_feerate_sat_per_1000_weight,
2446
+ htlc_descriptors,
2447
+ } ) ) ;
2448
+ }
2406
2449
}
2407
2450
}
2408
2451
ret
@@ -2623,31 +2666,49 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2623
2666
}
2624
2667
2625
2668
/// Attempts to claim a counterparty HTLC-Success/HTLC-Timeout's outputs using the revocation key
2626
- fn check_spend_counterparty_htlc < L : Deref > ( & mut self , tx : & Transaction , commitment_number : u64 , height : u32 , logger : & L ) -> ( Vec < PackageTemplate > , Option < TransactionOutputs > ) where L :: Target : Logger {
2627
- let htlc_txid = tx. txid ( ) ;
2628
- if tx. input . len ( ) != 1 || tx. output . len ( ) != 1 || tx. input [ 0 ] . witness . len ( ) != 5 {
2629
- return ( Vec :: new ( ) , None )
2630
- }
2631
-
2632
- macro_rules! ignore_error {
2633
- ( $thing : expr ) => {
2634
- match $thing {
2635
- Ok ( a) => a,
2636
- Err ( _) => return ( Vec :: new( ) , None )
2637
- }
2638
- } ;
2639
- }
2640
-
2669
+ fn check_spend_counterparty_htlc < L : Deref > (
2670
+ & mut self , tx : & Transaction , commitment_number : u64 , commitment_txid : & Txid , height : u32 , logger : & L
2671
+ ) -> ( Vec < PackageTemplate > , Option < TransactionOutputs > ) where L :: Target : Logger {
2641
2672
let secret = if let Some ( secret) = self . get_secret ( commitment_number) { secret } else { return ( Vec :: new ( ) , None ) ; } ;
2642
- let per_commitment_key = ignore_error ! ( SecretKey :: from_slice( & secret) ) ;
2673
+ let per_commitment_key = match SecretKey :: from_slice ( & secret) {
2674
+ Ok ( key) => key,
2675
+ Err ( _) => return ( Vec :: new ( ) , None )
2676
+ } ;
2643
2677
let per_commitment_point = PublicKey :: from_secret_key ( & self . secp_ctx , & per_commitment_key) ;
2644
2678
2645
- log_error ! ( logger, "Got broadcast of revoked counterparty HTLC transaction, spending {}:{}" , htlc_txid, 0 ) ;
2646
- let revk_outp = RevokedOutput :: build ( per_commitment_point, self . counterparty_commitment_params . counterparty_delayed_payment_base_key , self . counterparty_commitment_params . counterparty_htlc_base_key , per_commitment_key, tx. output [ 0 ] . value , self . counterparty_commitment_params . on_counterparty_tx_csv ) ;
2647
- let justice_package = PackageTemplate :: build_package ( htlc_txid, 0 , PackageSolvingData :: RevokedOutput ( revk_outp) , height + self . counterparty_commitment_params . on_counterparty_tx_csv as u32 , true , height) ;
2648
- let claimable_outpoints = vec ! ( justice_package) ;
2649
- let outputs = vec ! [ ( 0 , tx. output[ 0 ] . clone( ) ) ] ;
2650
- ( claimable_outpoints, Some ( ( htlc_txid, outputs) ) )
2679
+ let htlc_txid = tx. txid ( ) ;
2680
+ let mut claimable_outpoints = vec ! [ ] ;
2681
+ let mut outputs_to_watch = None ;
2682
+ // Previously, we would only claim HTLCs from revoked HTLC transactions if they had 1 input
2683
+ // with a witness of 5 elements and 1 output. This wasn't enough for anchor outputs, as the
2684
+ // counterparty can now aggregate multiple HTLCs into a single transaction thanks to
2685
+ // `SIGHASH_SINGLE` remote signatures, leading us to not claim any HTLCs upon seeing a
2686
+ // confirmed revoked HTLC transaction (for more details, see
2687
+ // https://lists.linuxfoundation.org/pipermail/lightning-dev/2022-April/003561.html).
2688
+ //
2689
+ // We make sure we're not vulnerable to this case by checking all inputs of the transaction,
2690
+ // and claim those which spend the commitment transaction, have a witness of 5 elements, and
2691
+ // have a corresponding output at the same index within the transaction.
2692
+ for ( idx, input) in tx. input . iter ( ) . enumerate ( ) {
2693
+ if input. previous_output . txid == * commitment_txid && input. witness . len ( ) == 5 && tx. output . get ( idx) . is_some ( ) {
2694
+ log_error ! ( logger, "Got broadcast of revoked counterparty HTLC transaction, spending {}:{}" , htlc_txid, idx) ;
2695
+ let revk_outp = RevokedOutput :: build (
2696
+ per_commitment_point, self . counterparty_commitment_params . counterparty_delayed_payment_base_key ,
2697
+ self . counterparty_commitment_params . counterparty_htlc_base_key , per_commitment_key,
2698
+ tx. output [ idx] . value , self . counterparty_commitment_params . on_counterparty_tx_csv
2699
+ ) ;
2700
+ let justice_package = PackageTemplate :: build_package (
2701
+ htlc_txid, idx as u32 , PackageSolvingData :: RevokedOutput ( revk_outp) ,
2702
+ height + self . counterparty_commitment_params . on_counterparty_tx_csv as u32 , true , height
2703
+ ) ;
2704
+ claimable_outpoints. push ( justice_package) ;
2705
+ if outputs_to_watch. is_none ( ) {
2706
+ outputs_to_watch = Some ( ( htlc_txid, vec ! [ ] ) ) ;
2707
+ }
2708
+ outputs_to_watch. as_mut ( ) . unwrap ( ) . 1 . push ( ( idx as u32 , tx. output [ idx] . clone ( ) ) ) ;
2709
+ }
2710
+ }
2711
+ ( claimable_outpoints, outputs_to_watch)
2651
2712
}
2652
2713
2653
2714
// Returns (1) `PackageTemplate`s that can be given to the OnchainTxHandler, so that the handler can
@@ -2661,18 +2722,28 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2661
2722
2662
2723
for & ( ref htlc, _, _) in holder_tx. htlc_outputs . iter ( ) {
2663
2724
if let Some ( transaction_output_index) = htlc. transaction_output_index {
2664
- let htlc_output = if htlc. offered {
2665
- HolderHTLCOutput :: build_offered ( htlc. amount_msat , htlc. cltv_expiry )
2725
+ let ( htlc_output, aggregable) = if htlc. offered {
2726
+ let htlc_output = HolderHTLCOutput :: build_offered (
2727
+ htlc. amount_msat , htlc. cltv_expiry , self . onchain_tx_handler . opt_anchors ( )
2728
+ ) ;
2729
+ ( htlc_output, false )
2730
+ } else {
2731
+ let payment_preimage = if let Some ( preimage) = self . payment_preimages . get ( & htlc. payment_hash ) {
2732
+ preimage. clone ( )
2666
2733
} else {
2667
- let payment_preimage = if let Some ( preimage) = self . payment_preimages . get ( & htlc. payment_hash ) {
2668
- preimage. clone ( )
2669
- } else {
2670
- // We can't build an HTLC-Success transaction without the preimage
2671
- continue ;
2672
- } ;
2673
- HolderHTLCOutput :: build_accepted ( payment_preimage, htlc. amount_msat )
2734
+ // We can't build an HTLC-Success transaction without the preimage
2735
+ continue ;
2674
2736
} ;
2675
- let htlc_package = PackageTemplate :: build_package ( holder_tx. txid , transaction_output_index, PackageSolvingData :: HolderHTLCOutput ( htlc_output) , htlc. cltv_expiry , false , conf_height) ;
2737
+ let htlc_output = HolderHTLCOutput :: build_accepted (
2738
+ payment_preimage, htlc. amount_msat , self . onchain_tx_handler . opt_anchors ( )
2739
+ ) ;
2740
+ ( htlc_output, self . onchain_tx_handler . opt_anchors ( ) )
2741
+ } ;
2742
+ let htlc_package = PackageTemplate :: build_package (
2743
+ holder_tx. txid , transaction_output_index,
2744
+ PackageSolvingData :: HolderHTLCOutput ( htlc_output) ,
2745
+ htlc. cltv_expiry , aggregable, conf_height
2746
+ ) ;
2676
2747
claim_requests. push ( htlc_package) ;
2677
2748
}
2678
2749
}
@@ -2905,9 +2976,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2905
2976
2906
2977
if tx. input . len ( ) == 1 {
2907
2978
// Assuming our keys were not leaked (in which case we're screwed no matter what),
2908
- // commitment transactions and HTLC transactions will all only ever have one input,
2909
- // which is an easy way to filter out any potential non-matching txn for lazy
2910
- // filters.
2979
+ // commitment transactions and HTLC transactions will all only ever have one input
2980
+ // (except for HTLC transactions for channels with anchor outputs), which is an easy
2981
+ // way to filter out any potential non-matching txn for lazy filters.
2911
2982
let prevout = & tx. input [ 0 ] . previous_output ;
2912
2983
if prevout. txid == self . funding_info . 0 . txid && prevout. vout == self . funding_info . 0 . index as u32 {
2913
2984
let mut balance_spendable_csv = None ;
@@ -2945,22 +3016,33 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2945
3016
commitment_tx_to_counterparty_output,
2946
3017
} ,
2947
3018
} ) ;
2948
- } else {
2949
- if let Some ( & commitment_number) = self . counterparty_commitment_txn_on_chain . get ( & prevout. txid ) {
2950
- let ( mut new_outpoints, new_outputs_option) = self . check_spend_counterparty_htlc ( & tx, commitment_number, height, & logger) ;
3019
+ }
3020
+ }
3021
+ if tx. input . len ( ) >= 1 {
3022
+ // While all commitment transactions have one input, HTLC transactions may have more
3023
+ // if the HTLC was present in an anchor channel. HTLCs can also be resolved in a few
3024
+ // other ways which can have more than one output.
3025
+ for tx_input in & tx. input {
3026
+ let commitment_txid = tx_input. previous_output . txid ;
3027
+ if let Some ( & commitment_number) = self . counterparty_commitment_txn_on_chain . get ( & commitment_txid) {
3028
+ let ( mut new_outpoints, new_outputs_option) = self . check_spend_counterparty_htlc (
3029
+ & tx, commitment_number, & commitment_txid, height, & logger
3030
+ ) ;
2951
3031
claimable_outpoints. append ( & mut new_outpoints) ;
2952
3032
if let Some ( new_outputs) = new_outputs_option {
2953
3033
watch_outputs. push ( new_outputs) ;
2954
3034
}
3035
+ // Since there may be multiple HTLCs (all from the same commitment) being
3036
+ // claimed by the counterparty within the same transaction, and
3037
+ // `check_spend_counterparty_htlc` already checks for all of them, we can
3038
+ // safely break from our loop.
3039
+ break ;
2955
3040
}
2956
3041
}
2957
- }
2958
- // While all commitment/HTLC-Success/HTLC-Timeout transactions have one input, HTLCs
2959
- // can also be resolved in a few other ways which can have more than one output. Thus,
2960
- // we call is_resolving_htlc_output here outside of the tx.input.len() == 1 check.
2961
- self . is_resolving_htlc_output ( & tx, height, & block_hash, & logger) ;
3042
+ self . is_resolving_htlc_output ( & tx, height, & block_hash, & logger) ;
2962
3043
2963
- self . is_paying_spendable_output ( & tx, height, & block_hash, & logger) ;
3044
+ self . is_paying_spendable_output ( & tx, height, & block_hash, & logger) ;
3045
+ }
2964
3046
}
2965
3047
2966
3048
if height > self . best_block . height ( ) {
@@ -3074,7 +3156,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
3074
3156
htlc_value_satoshis,
3075
3157
} ) ) ;
3076
3158
self . htlcs_resolved_on_chain . push ( IrrevocablyResolvedHTLC {
3077
- commitment_tx_output_idx, resolving_txid : Some ( entry. txid ) ,
3159
+ commitment_tx_output_idx,
3160
+ resolving_txid : Some ( entry. txid ) ,
3161
+ resolving_tx : entry. transaction ,
3078
3162
payment_preimage : None ,
3079
3163
} ) ;
3080
3164
} ,
@@ -3087,7 +3171,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
3087
3171
} ,
3088
3172
OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } => {
3089
3173
self . htlcs_resolved_on_chain . push ( IrrevocablyResolvedHTLC {
3090
- commitment_tx_output_idx : Some ( commitment_tx_output_idx) , resolving_txid : Some ( entry. txid ) ,
3174
+ commitment_tx_output_idx : Some ( commitment_tx_output_idx) ,
3175
+ resolving_txid : Some ( entry. txid ) ,
3176
+ resolving_tx : entry. transaction ,
3091
3177
payment_preimage : preimage,
3092
3178
} ) ;
3093
3179
} ,
0 commit comments