@@ -53,7 +53,7 @@ use crate::util::ser::{Readable, ReadableArgs, MaybeReadable, Writer, Writeable,
5353use crate :: util:: byte_utils;
5454use crate :: util:: events:: Event ;
5555#[ cfg( anchors) ]
56- use crate :: util:: events:: { AnchorDescriptor , BumpTransactionEvent } ;
56+ use crate :: util:: events:: { AnchorDescriptor , HTLCDescriptor , BumpTransactionEvent } ;
5757
5858use crate :: prelude:: * ;
5959use core:: { cmp, mem} ;
@@ -647,6 +647,7 @@ struct IrrevocablyResolvedHTLC {
647647 /// was not present in the confirmed commitment transaction), HTLC-Success, or HTLC-Timeout
648648 /// transaction.
649649 resolving_txid : Option < Txid > , // Added as optional, but always filled in, in 0.0.110
650+ resolving_tx : Option < Transaction > ,
650651 /// Only set if the HTLC claim was ours using a payment preimage
651652 payment_preimage : Option < PaymentPreimage > ,
652653}
@@ -662,6 +663,7 @@ impl Writeable for IrrevocablyResolvedHTLC {
662663 ( 0 , mapped_commitment_tx_output_idx, required) ,
663664 ( 1 , self . resolving_txid, option) ,
664665 ( 2 , self . payment_preimage, option) ,
666+ ( 3 , self . resolving_tx, option) ,
665667 } ) ;
666668 Ok ( ( ) )
667669 }
@@ -672,15 +674,18 @@ impl Readable for IrrevocablyResolvedHTLC {
672674 let mut mapped_commitment_tx_output_idx = 0 ;
673675 let mut resolving_txid = None ;
674676 let mut payment_preimage = None ;
677+ let mut resolving_tx = None ;
675678 read_tlv_fields ! ( reader, {
676679 ( 0 , mapped_commitment_tx_output_idx, required) ,
677680 ( 1 , resolving_txid, option) ,
678681 ( 2 , payment_preimage, option) ,
682+ ( 3 , resolving_tx, option) ,
679683 } ) ;
680684 Ok ( Self {
681685 commitment_tx_output_idx : if mapped_commitment_tx_output_idx == u32:: max_value ( ) { None } else { Some ( mapped_commitment_tx_output_idx) } ,
682686 resolving_txid,
683687 payment_preimage,
688+ resolving_tx,
684689 } )
685690 }
686691}
@@ -1526,6 +1531,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
15261531 if let Some ( v) = htlc. transaction_output_index { v } else { return None ; } ;
15271532
15281533 let mut htlc_spend_txid_opt = None ;
1534+ let mut htlc_spend_tx_opt = None ;
15291535 let mut holder_timeout_spend_pending = None ;
15301536 let mut htlc_spend_pending = None ;
15311537 let mut holder_delayed_output_pending = None ;
@@ -1534,15 +1540,19 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
15341540 OnchainEvent :: HTLCUpdate { commitment_tx_output_idx, htlc_value_satoshis, .. }
15351541 if commitment_tx_output_idx == Some ( htlc_commitment_tx_output_idx) => {
15361542 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 ( ) ;
15381546 debug_assert ! ( holder_timeout_spend_pending. is_none( ) ) ;
15391547 debug_assert_eq ! ( htlc_value_satoshis. unwrap( ) , htlc. amount_msat / 1000 ) ;
15401548 holder_timeout_spend_pending = Some ( event. confirmation_threshold ( ) ) ;
15411549 } ,
15421550 OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. }
15431551 if commitment_tx_output_idx == htlc_commitment_tx_output_idx => {
15441552 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 ( ) ;
15461556 debug_assert ! ( htlc_spend_pending. is_none( ) ) ;
15471557 htlc_spend_pending = Some ( ( event. confirmation_threshold ( ) , preimage. is_some ( ) ) ) ;
15481558 } ,
@@ -1558,19 +1568,32 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
15581568 let htlc_resolved = self . htlcs_resolved_on_chain . iter ( )
15591569 . find ( |v| if v. commitment_tx_output_idx == Some ( htlc_commitment_tx_output_idx) {
15601570 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 ( ) ;
15621574 true
15631575 } else { false } ) ;
15641576 debug_assert ! ( holder_timeout_spend_pending. is_some( ) as u8 + htlc_spend_pending. is_some( ) as u8 + htlc_resolved. is_some( ) as u8 <= 1 ) ;
15651577
1578+ let htlc_commitment_outpoint = BitcoinOutPoint :: new ( confirmed_txid. unwrap ( ) , htlc_commitment_tx_output_idx) ;
15661579 let htlc_output_to_spend =
15671580 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+ }
15721595 } else {
1573- BitcoinOutPoint :: new ( confirmed_txid . unwrap ( ) , htlc_commitment_tx_output_idx )
1596+ htlc_commitment_outpoint
15741597 } ;
15751598 let htlc_output_spend_pending = self . onchain_tx_handler . is_output_spend_pending ( & htlc_output_to_spend) ;
15761599
@@ -1594,8 +1617,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
15941617 } = & event. event {
15951618 if event. transaction . as_ref ( ) . map ( |tx| tx. input . iter ( ) . any ( |inp| {
15961619 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
15991621 } else {
16001622 Some ( inp. previous_output . txid ) == confirmed_txid &&
16011623 inp. previous_output . vout == htlc_commitment_tx_output_idx
@@ -2403,6 +2425,27 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
24032425 pending_htlcs,
24042426 } ) ) ;
24052427 } ,
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+ }
24062449 }
24072450 }
24082451 ret
@@ -2623,31 +2666,49 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
26232666 }
26242667
26252668 /// 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 {
26412672 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+ } ;
26432677 let per_commitment_point = PublicKey :: from_secret_key ( & self . secp_ctx , & per_commitment_key) ;
26442678
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)
26512712 }
26522713
26532714 // 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> {
26612722
26622723 for & ( ref htlc, _, _) in holder_tx. htlc_outputs . iter ( ) {
26632724 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 ( )
26662733 } 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 ;
26742736 } ;
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+ ) ;
26762747 claim_requests. push ( htlc_package) ;
26772748 }
26782749 }
@@ -2905,9 +2976,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
29052976
29062977 if tx. input . len ( ) == 1 {
29072978 // 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.
29112982 let prevout = & tx. input [ 0 ] . previous_output ;
29122983 if prevout. txid == self . funding_info . 0 . txid && prevout. vout == self . funding_info . 0 . index as u32 {
29132984 let mut balance_spendable_csv = None ;
@@ -2945,22 +3016,33 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
29453016 commitment_tx_to_counterparty_output,
29463017 } ,
29473018 } ) ;
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+ ) ;
29513031 claimable_outpoints. append ( & mut new_outpoints) ;
29523032 if let Some ( new_outputs) = new_outputs_option {
29533033 watch_outputs. push ( new_outputs) ;
29543034 }
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 ;
29553040 }
29563041 }
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) ;
29623043
2963- self . is_paying_spendable_output ( & tx, height, & block_hash, & logger) ;
3044+ self . is_paying_spendable_output ( & tx, height, & block_hash, & logger) ;
3045+ }
29643046 }
29653047
29663048 if height > self . best_block . height ( ) {
@@ -3074,7 +3156,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
30743156 htlc_value_satoshis,
30753157 } ) ) ;
30763158 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 ,
30783162 payment_preimage : None ,
30793163 } ) ;
30803164 } ,
@@ -3087,7 +3171,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
30873171 } ,
30883172 OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } => {
30893173 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 ,
30913177 payment_preimage : preimage,
30923178 } ) ;
30933179 } ,
0 commit comments