@@ -849,8 +849,8 @@ where
849849 /// Handles a [`BumpTransactionEvent::HTLCResolution`] event variant by producing a
850850 /// fully-signed, fee-bumped HTLC transaction that is broadcast to the network.
851851 async fn handle_htlc_resolution (
852- & self , target_feerate_sat_per_1000_weight : u32 , htlc_descriptors : & [ HTLCDescriptor ] ,
853- tx_lock_time : LockTime ,
852+ & self , claim_id : ClaimId , target_feerate_sat_per_1000_weight : u32 ,
853+ htlc_descriptors : & [ HTLCDescriptor ] , tx_lock_time : LockTime ,
854854 ) -> Result < ( ) , ( ) > {
855855 let channel_type = & htlc_descriptors[ 0 ]
856856 . channel_derivation_parameters
@@ -885,29 +885,14 @@ where
885885 // and 483 * 705 ~= 341_000, and 341_000 < 400_000.
886886 chan_utils:: MAX_STANDARD_TX_WEIGHT
887887 } ;
888+ // A 1-input 1-output transaction, both p2wpkh is 438 WU.
889+ // If the coins go above this limit, it's ok we pop a few HTLCs and try again.
890+ const USER_COINS_WEIGHT_BUDGET : u64 = 1000 ;
891+
888892 let mut broadcasted_htlcs = 0 ;
889893 let mut batch_size = htlc_descriptors. len ( ) - broadcasted_htlcs;
890894
891895 while broadcasted_htlcs < htlc_descriptors. len ( ) {
892- let htlcs = & htlc_descriptors[ broadcasted_htlcs..broadcasted_htlcs + batch_size] ;
893- // Generate a new claim_id to map a user-provided utxo to this
894- // particular set of HTLCs via `select_confirmed_utxos`.
895- //
896- // This matches the scheme used in `onchaintx.rs`, so for non-0fc-channels,
897- // this should match the `ClaimId` of the claim generated in `onchaintx.rs`.
898- let mut engine = Sha256 :: engine ( ) ;
899- for htlc in htlcs {
900- engine. input ( & htlc. commitment_txid . to_byte_array ( ) ) ;
901- engine. input ( & htlc. htlc . transaction_output_index . unwrap ( ) . to_be_bytes ( ) ) ;
902- }
903- let utxo_id = ClaimId ( Sha256 :: from_engine ( engine) . to_byte_array ( ) ) ;
904- log_info ! (
905- self . logger,
906- "Batch transaction assigned to UTXO id {} contains {} HTLCs: {}" ,
907- log_bytes!( utxo_id. 0 ) ,
908- htlcs. len( ) ,
909- log_iter!( htlcs. iter( ) . map( |d| d. outpoint( ) ) )
910- ) ;
911896 let mut htlc_tx = Transaction {
912897 version : if channel_type. supports_anchor_zero_fee_commitments ( ) {
913898 Version :: non_standard ( 3 )
@@ -918,8 +903,20 @@ where
918903 input : vec ! [ ] ,
919904 output : vec ! [ ] ,
920905 } ;
921- let mut must_spend = Vec :: with_capacity ( htlcs. len ( ) ) ;
922- for htlc_descriptor in htlcs {
906+ let mut must_spend = Vec :: with_capacity ( htlc_descriptors. len ( ) - broadcasted_htlcs) ;
907+ let mut htlc_weight_sum = 0 ;
908+ for htlc_descriptor in
909+ & htlc_descriptors[ broadcasted_htlcs..broadcasted_htlcs + batch_size]
910+ {
911+ let input_output_weight = if htlc_descriptor. preimage . is_some ( ) {
912+ chan_utils:: htlc_success_input_output_pair_weight ( channel_type)
913+ } else {
914+ chan_utils:: htlc_timeout_input_output_pair_weight ( channel_type)
915+ } ;
916+ if htlc_weight_sum + input_output_weight >= max_weight - USER_COINS_WEIGHT_BUDGET {
917+ break ;
918+ }
919+ htlc_weight_sum += input_output_weight;
923920 let htlc_input = htlc_descriptor. unsigned_tx_input ( ) ;
924921 must_spend. push ( Input {
925922 outpoint : htlc_input. previous_output . clone ( ) ,
@@ -935,6 +932,30 @@ where
935932 let htlc_output = htlc_descriptor. tx_output ( & self . secp ) ;
936933 htlc_tx. output . push ( htlc_output) ;
937934 }
935+ batch_size = htlc_tx. input . len ( ) ;
936+ let selected_htlcs =
937+ & htlc_descriptors[ broadcasted_htlcs..broadcasted_htlcs + batch_size] ;
938+
939+ let utxo_id = if broadcasted_htlcs == 0 {
940+ claim_id
941+ } else {
942+ // Generate a new claim_id to map a user-provided utxo to this
943+ // particular set of HTLCs via `select_confirmed_utxos`.
944+ let mut engine = Sha256 :: engine ( ) ;
945+ for htlc in selected_htlcs {
946+ engine. input ( & htlc. commitment_txid . to_byte_array ( ) ) ;
947+ engine. input ( & htlc. htlc . transaction_output_index . unwrap ( ) . to_be_bytes ( ) ) ;
948+ }
949+ ClaimId ( Sha256 :: from_engine ( engine) . to_byte_array ( ) )
950+ } ;
951+
952+ log_info ! (
953+ self . logger,
954+ "Batch transaction assigned to UTXO id {} contains {} HTLCs: {}" ,
955+ log_bytes!( utxo_id. 0 ) ,
956+ batch_size,
957+ log_iter!( selected_htlcs. iter( ) . map( |d| d. outpoint( ) ) )
958+ ) ;
938959
939960 log_debug ! (
940961 self . logger,
@@ -988,7 +1009,7 @@ where
9881009 // construct psbt
9891010 let mut htlc_psbt = Psbt :: from_unsigned_tx ( htlc_tx) . unwrap ( ) ;
9901011 // add witness_utxo to htlc inputs
991- for ( i, htlc_descriptor) in htlcs . iter ( ) . enumerate ( ) {
1012+ for ( i, htlc_descriptor) in selected_htlcs . iter ( ) . enumerate ( ) {
9921013 debug_assert_eq ! (
9931014 htlc_psbt. unsigned_tx. input[ i] . previous_output,
9941015 htlc_descriptor. outpoint( )
@@ -999,7 +1020,7 @@ where
9991020 // add witness_utxo to remaining inputs
10001021 for ( idx, utxo) in coin_selection. confirmed_utxos . into_iter ( ) . enumerate ( ) {
10011022 // offset to skip the htlc inputs
1002- let index = idx + htlcs . len ( ) ;
1023+ let index = idx + selected_htlcs . len ( ) ;
10031024 debug_assert_eq ! ( htlc_psbt. unsigned_tx. input[ index] . previous_output, utxo. outpoint) ;
10041025 if utxo. output . script_pubkey . is_witness_program ( ) {
10051026 htlc_psbt. inputs [ index] . witness_utxo = Some ( utxo. output ) ;
@@ -1014,7 +1035,7 @@ where
10141035 let mut htlc_tx = self . utxo_source . sign_psbt ( htlc_psbt) . await ?;
10151036
10161037 let mut signers = BTreeMap :: new ( ) ;
1017- for ( idx, htlc_descriptor) in htlcs . iter ( ) . enumerate ( ) {
1038+ for ( idx, htlc_descriptor) in selected_htlcs . iter ( ) . enumerate ( ) {
10181039 let keys_id = htlc_descriptor. channel_derivation_parameters . keys_id ;
10191040 let signer = signers
10201041 . entry ( keys_id)
@@ -1101,6 +1122,7 @@ where
11011122 log_iter!( htlc_descriptors. iter( ) . map( |d| d. outpoint( ) ) )
11021123 ) ;
11031124 self . handle_htlc_resolution (
1125+ * claim_id,
11041126 * target_feerate_sat_per_1000_weight,
11051127 htlc_descriptors,
11061128 * tx_lock_time,
0 commit comments