@@ -582,11 +582,25 @@ where
582582 // match, but we still need to have at least one output in the transaction for it to be
583583 // considered standard. We choose to go with an empty OP_RETURN as it is the cheapest
584584 // way to include a dummy output.
585- log_debug ! ( self . logger, "Including dummy OP_RETURN output since an output is needed and a change output was not provided" ) ;
586- tx. output . push ( TxOut {
587- value : Amount :: ZERO ,
588- script_pubkey : ScriptBuf :: new_op_return ( & [ ] ) ,
589- } ) ;
585+ if tx. input . len ( ) <= 1 {
586+ // Transactions have to be at least 65 bytes in non-witness data, which we can run
587+ // under if we have too few witness inputs.
588+ log_debug ! ( self . logger, "Including large OP_RETURN output since an output is needed and a change output was not provided and the transaction is small" ) ;
589+ debug_assert ! ( !tx. input. is_empty( ) ) ;
590+ tx. output . push ( TxOut {
591+ value : Amount :: ZERO ,
592+ // Minimum transaction size is 60 bytes, so we need a 5-byte script to get a
593+ // 65 byte transaction. We do that as OP_RETURN <3 0 bytes, plus 1 byte len>.
594+ script_pubkey : ScriptBuf :: new_op_return ( & [ 0 , 0 , 0 ] ) ,
595+ } ) ;
596+ debug_assert_eq ! ( tx. base_size( ) , 65 ) ;
597+ } else {
598+ log_debug ! ( self . logger, "Including dummy OP_RETURN output since an output is needed and a change output was not provided" ) ;
599+ tx. output . push ( TxOut {
600+ value : Amount :: ZERO ,
601+ script_pubkey : ScriptBuf :: new_op_return ( & [ ] ) ,
602+ } ) ;
603+ }
590604 }
591605 }
592606
@@ -603,85 +617,102 @@ where
603617 let mut anchor_utxo = anchor_descriptor. previous_utxo ( ) ;
604618 let commitment_tx_fee_sat = Amount :: from_sat ( commitment_tx_fee_sat) ;
605619 anchor_utxo. value += commitment_tx_fee_sat;
606- let must_spend = vec ! [ Input {
607- outpoint: anchor_descriptor. outpoint,
608- previous_utxo: anchor_utxo,
609- satisfaction_weight: commitment_tx. weight( ) . to_wu( ) + ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT ,
610- } ] ;
611- #[ cfg( debug_assertions) ]
612- let must_spend_amount = must_spend. iter ( ) . map ( |input| input. previous_utxo . value ) . sum :: < Amount > ( ) ;
613-
614- log_debug ! ( self . logger, "Performing coin selection for commitment package (commitment and anchor transaction) targeting {} sat/kW" ,
615- package_target_feerate_sat_per_1000_weight) ;
616- let coin_selection: CoinSelection = self . utxo_source . select_confirmed_utxos (
617- claim_id, must_spend, & [ ] , package_target_feerate_sat_per_1000_weight,
618- ) ?;
619-
620- let mut anchor_tx = Transaction {
621- version : Version :: TWO ,
622- lock_time : LockTime :: ZERO , // TODO: Use next best height.
623- input : vec ! [ anchor_descriptor. unsigned_tx_input( ) ] ,
624- output : vec ! [ ] ,
625- } ;
626-
627- #[ cfg( debug_assertions) ]
628- let total_satisfaction_weight = ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT +
629- coin_selection. confirmed_utxos . iter ( ) . map ( |utxo| utxo. satisfaction_weight ) . sum :: < u64 > ( ) ;
630- #[ cfg( debug_assertions) ]
631- let total_input_amount = must_spend_amount +
632- coin_selection. confirmed_utxos . iter ( ) . map ( |utxo| utxo. output . value ) . sum ( ) ;
633-
634- self . process_coin_selection ( & mut anchor_tx, & coin_selection) ;
635- let anchor_txid = anchor_tx. compute_txid ( ) ;
620+ let starting_package_and_fixed_input_satisfaction_weight =
621+ commitment_tx. weight ( ) . to_wu ( ) + ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT ;
622+ let mut package_and_fixed_input_satisfaction_weight =
623+ starting_package_and_fixed_input_satisfaction_weight;
624+
625+ loop {
626+ let must_spend = vec ! [ Input {
627+ outpoint: anchor_descriptor. outpoint,
628+ previous_utxo: anchor_utxo. clone( ) ,
629+ satisfaction_weight: package_and_fixed_input_satisfaction_weight,
630+ } ] ;
631+ let must_spend_amount = must_spend. iter ( ) . map ( |input| input. previous_utxo . value ) . sum :: < Amount > ( ) ;
632+
633+ log_debug ! ( self . logger, "Performing coin selection for commitment package (commitment and anchor transaction) targeting {} sat/kW" ,
634+ package_target_feerate_sat_per_1000_weight) ;
635+ let coin_selection: CoinSelection = self . utxo_source . select_confirmed_utxos (
636+ claim_id, must_spend, & [ ] , package_target_feerate_sat_per_1000_weight,
637+ ) ?;
638+
639+ let mut anchor_tx = Transaction {
640+ version : Version :: TWO ,
641+ lock_time : LockTime :: ZERO , // TODO: Use next best height.
642+ input : vec ! [ anchor_descriptor. unsigned_tx_input( ) ] ,
643+ output : vec ! [ ] ,
644+ } ;
636645
637- // construct psbt
638- let mut anchor_psbt = Psbt :: from_unsigned_tx ( anchor_tx) . unwrap ( ) ;
639- // add witness_utxo to anchor input
640- anchor_psbt. inputs [ 0 ] . witness_utxo = Some ( anchor_descriptor. previous_utxo ( ) ) ;
641- // add witness_utxo to remaining inputs
642- for ( idx, utxo) in coin_selection. confirmed_utxos . into_iter ( ) . enumerate ( ) {
643- // add 1 to skip the anchor input
644- let index = idx + 1 ;
645- debug_assert_eq ! ( anchor_psbt. unsigned_tx. input[ index] . previous_output, utxo. outpoint) ;
646- if utxo. output . script_pubkey . is_witness_program ( ) {
647- anchor_psbt. inputs [ index] . witness_utxo = Some ( utxo. output ) ;
646+ let total_satisfaction_weight = ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT +
647+ coin_selection. confirmed_utxos . iter ( ) . map ( |utxo| utxo. satisfaction_weight ) . sum :: < u64 > ( ) ;
648+ let total_input_amount = must_spend_amount +
649+ coin_selection. confirmed_utxos . iter ( ) . map ( |utxo| utxo. output . value ) . sum ( ) ;
650+
651+ self . process_coin_selection ( & mut anchor_tx, & coin_selection) ;
652+ let anchor_txid = anchor_tx. compute_txid ( ) ;
653+
654+ // construct psbt
655+ let mut anchor_psbt = Psbt :: from_unsigned_tx ( anchor_tx) . unwrap ( ) ;
656+ // add witness_utxo to anchor input
657+ anchor_psbt. inputs [ 0 ] . witness_utxo = Some ( anchor_descriptor. previous_utxo ( ) ) ;
658+ // add witness_utxo to remaining inputs
659+ for ( idx, utxo) in coin_selection. confirmed_utxos . into_iter ( ) . enumerate ( ) {
660+ // add 1 to skip the anchor input
661+ let index = idx + 1 ;
662+ debug_assert_eq ! ( anchor_psbt. unsigned_tx. input[ index] . previous_output, utxo. outpoint) ;
663+ if utxo. output . script_pubkey . is_witness_program ( ) {
664+ anchor_psbt. inputs [ index] . witness_utxo = Some ( utxo. output ) ;
665+ }
648666 }
649- }
650-
651- debug_assert_eq ! ( anchor_psbt. unsigned_tx. output. len( ) , 1 ) ;
652- #[ cfg( debug_assertions) ]
653- let unsigned_tx_weight = anchor_psbt. unsigned_tx . weight ( ) . to_wu ( ) - ( anchor_psbt. unsigned_tx . input . len ( ) as u64 * EMPTY_SCRIPT_SIG_WEIGHT ) ;
654667
655- log_debug ! ( self . logger , "Signing anchor transaction {}" , anchor_txid ) ;
656- anchor_tx = self . utxo_source . sign_psbt ( anchor_psbt) ? ;
668+ debug_assert_eq ! ( anchor_psbt . unsigned_tx . output . len ( ) , 1 ) ;
669+ let unsigned_tx_weight = anchor_psbt . unsigned_tx . weight ( ) . to_wu ( ) - ( anchor_psbt. unsigned_tx . input . len ( ) as u64 * EMPTY_SCRIPT_SIG_WEIGHT ) ;
657670
658- let signer = anchor_descriptor. derive_channel_signer ( & self . signer_provider ) ;
659- let anchor_sig = signer. sign_holder_anchor_input ( & anchor_tx, 0 , & self . secp ) ?;
660- anchor_tx. input [ 0 ] . witness = anchor_descriptor. tx_input_witness ( & anchor_sig) ;
671+ let package_fee = total_input_amount -
672+ anchor_psbt. unsigned_tx . output . iter ( ) . map ( |output| output. value ) . sum ( ) ;
673+ let package_weight = unsigned_tx_weight + 2 /* wit marker */ + total_satisfaction_weight + commitment_tx. weight ( ) . to_wu ( ) ;
674+ if package_fee. to_sat ( ) * 1000 / package_weight < package_target_feerate_sat_per_1000_weight. into ( ) {
675+ // On the first iteration of the loop, we may undershoot the target feerate because
676+ // we had to add an OP_RETURN output in `process_coin_selection` which we didn't
677+ // select sufficient coins for. Here we detect that case and go around again
678+ // seeking additional weight.
679+ if package_and_fixed_input_satisfaction_weight == starting_package_and_fixed_input_satisfaction_weight {
680+ debug_assert ! ( anchor_psbt. unsigned_tx. output[ 0 ] . script_pubkey. is_op_return( ) ,
681+ "Coin selection failed to select sufficient coins for its change output" ) ;
682+ package_and_fixed_input_satisfaction_weight += anchor_psbt. unsigned_tx . output [ 0 ] . weight ( ) . to_wu ( ) ;
683+ continue ;
684+ } else {
685+ debug_assert ! ( false , "Coin selection failed to select sufficient coins" ) ;
686+ }
687+ }
661688
662- #[ cfg( debug_assertions) ] {
663- let signed_tx_weight = anchor_tx. weight ( ) . to_wu ( ) ;
664- let expected_signed_tx_weight = unsigned_tx_weight + total_satisfaction_weight;
665- // Our estimate should be within a 1% error margin of the actual weight and we should
666- // never underestimate.
667- assert ! ( expected_signed_tx_weight >= signed_tx_weight &&
668- expected_signed_tx_weight - ( expected_signed_tx_weight / 100 ) <= signed_tx_weight) ;
689+ log_debug ! ( self . logger, "Signing anchor transaction {}" , anchor_txid) ;
690+ anchor_tx = self . utxo_source . sign_psbt ( anchor_psbt) ?;
691+
692+ let signer = anchor_descriptor. derive_channel_signer ( & self . signer_provider ) ;
693+ let anchor_sig = signer. sign_holder_anchor_input ( & anchor_tx, 0 , & self . secp ) ?;
694+ anchor_tx. input [ 0 ] . witness = anchor_descriptor. tx_input_witness ( & anchor_sig) ;
695+
696+ #[ cfg( debug_assertions) ] {
697+ let signed_tx_weight = anchor_tx. weight ( ) . to_wu ( ) ;
698+ let expected_signed_tx_weight = unsigned_tx_weight + 2 /* wit marker */ + total_satisfaction_weight;
699+ // Our estimate should be within a 1% error margin of the actual weight and we should
700+ // never underestimate.
701+ assert ! ( expected_signed_tx_weight >= signed_tx_weight &&
702+ expected_signed_tx_weight - ( expected_signed_tx_weight / 100 ) <= signed_tx_weight) ;
703+
704+ let expected_package_fee = Amount :: from_sat ( fee_for_weight ( package_target_feerate_sat_per_1000_weight,
705+ signed_tx_weight + commitment_tx. weight ( ) . to_wu ( ) ) ) ;
706+ // Our feerate should always be at least what we were seeking. It may overshoot if
707+ // the coin selector burned funds to an OP_RETURN without a change output.
708+ assert ! ( package_fee >= expected_package_fee) ;
709+ }
669710
670- let expected_package_fee = Amount :: from_sat ( fee_for_weight ( package_target_feerate_sat_per_1000_weight,
671- signed_tx_weight + commitment_tx. weight ( ) . to_wu ( ) ) ) ;
672- let package_fee = total_input_amount -
673- anchor_tx. output . iter ( ) . map ( |output| output. value ) . sum ( ) ;
674- // Our fee should be within a 5% error margin of the expected fee based on the
675- // feerate and transaction weight and we should never pay less than required.
676- let fee_error_margin = expected_package_fee * 5 / 100 ;
677- assert ! ( package_fee >= expected_package_fee &&
678- package_fee - fee_error_margin <= expected_package_fee) ;
711+ log_info ! ( self . logger, "Broadcasting anchor transaction {} to bump channel close with txid {}" ,
712+ anchor_txid, commitment_tx. compute_txid( ) ) ;
713+ self . broadcaster . broadcast_transactions ( & [ & commitment_tx, & anchor_tx] ) ;
714+ return Ok ( ( ) ) ;
679715 }
680-
681- log_info ! ( self . logger, "Broadcasting anchor transaction {} to bump channel close with txid {}" ,
682- anchor_txid, commitment_tx. compute_txid( ) ) ;
683- self . broadcaster . broadcast_transactions ( & [ & commitment_tx, & anchor_tx] ) ;
684- Ok ( ( ) )
685716 }
686717
687718 /// Handles a [`BumpTransactionEvent::HTLCResolution`] event variant by producing a
@@ -778,11 +809,9 @@ where
778809 let expected_signed_tx_fee = fee_for_weight ( target_feerate_sat_per_1000_weight, signed_tx_weight) ;
779810 let signed_tx_fee = total_input_amount -
780811 htlc_tx. output . iter ( ) . map ( |output| output. value . to_sat ( ) ) . sum :: < u64 > ( ) ;
781- // Our fee should be within a 5% error margin of the expected fee based on the
782- // feerate and transaction weight and we should never pay less than required.
783- let fee_error_margin = expected_signed_tx_fee * 5 / 100 ;
784- assert ! ( signed_tx_fee >= expected_signed_tx_fee &&
785- signed_tx_fee - fee_error_margin <= expected_signed_tx_fee) ;
812+ // Our feerate should always be at least what we were seeking. It may overshoot if
813+ // the coin selector burned funds to an OP_RETURN without a change output.
814+ assert ! ( signed_tx_fee >= expected_signed_tx_fee) ;
786815 }
787816
788817 log_info ! ( self . logger, "Broadcasting {}" , log_tx!( htlc_tx) ) ;
@@ -822,3 +851,116 @@ where
822851 }
823852 }
824853}
854+
855+ #[ cfg( test) ]
856+ mod tests {
857+ use super :: * ;
858+
859+ use crate :: io:: Cursor ;
860+ use crate :: ln:: chan_utils:: ChannelTransactionParameters ;
861+ use crate :: util:: ser:: Readable ;
862+ use crate :: util:: test_utils:: { TestBroadcaster , TestLogger } ;
863+ use crate :: sign:: KeysManager ;
864+
865+ use bitcoin:: hashes:: Hash ;
866+ use bitcoin:: hex:: FromHex ;
867+ use bitcoin:: { Network , ScriptBuf , Transaction , Txid } ;
868+
869+ struct TestCoinSelectionSource {
870+ // (commitment + anchor value, commitment + input weight, target feerate, result)
871+ expected_selects : Mutex < Vec < ( u64 , u64 , u32 , CoinSelection ) > > ,
872+ }
873+ impl CoinSelectionSource for TestCoinSelectionSource {
874+ fn select_confirmed_utxos (
875+ & self ,
876+ _claim_id : ClaimId ,
877+ must_spend : Vec < Input > ,
878+ _must_pay_to : & [ TxOut ] ,
879+ target_feerate_sat_per_1000_weight : u32
880+ ) -> Result < CoinSelection , ( ) > {
881+ let mut expected_selects = self . expected_selects . lock ( ) . unwrap ( ) ;
882+ let ( weight, value, feerate, res) = expected_selects. remove ( 0 ) ;
883+ assert_eq ! ( must_spend. len( ) , 1 ) ;
884+ assert_eq ! ( must_spend[ 0 ] . satisfaction_weight, weight) ;
885+ assert_eq ! ( must_spend[ 0 ] . previous_utxo. value. to_sat( ) , value) ;
886+ assert_eq ! ( target_feerate_sat_per_1000_weight, feerate) ;
887+ Ok ( res)
888+ }
889+ fn sign_psbt ( & self , psbt : Psbt ) -> Result < Transaction , ( ) > {
890+ let mut tx = psbt. unsigned_tx ;
891+ for input in tx. input . iter_mut ( ) {
892+ if input. previous_output . txid != Txid :: from_byte_array ( [ 44 ; 32 ] ) {
893+ // Channel output, add a realistic size witness to make the assertions happy
894+ input. witness = Witness :: from_slice ( & [ vec ! [ 42 ; 162 ] ] ) ;
895+ }
896+ }
897+ Ok ( tx)
898+ }
899+ }
900+
901+ impl Drop for TestCoinSelectionSource {
902+ fn drop ( & mut self ) {
903+ assert ! ( self . expected_selects. lock( ) . unwrap( ) . is_empty( ) ) ;
904+ }
905+ }
906+
907+ #[ test]
908+ fn test_op_return_under_funds ( ) {
909+ // Test what happens if we have to select coins but the anchor output value itself suffices
910+ // to pay the required fee.
911+ //
912+ // This tests a case that occurred on mainnet (with the below transaction) where the target
913+ // feerate (of 868 sat/kW) was met by the anchor output's 330 sats alone. This caused the
914+ // use of an OP_RETURN which created a transaction which, at the time, was less than 64
915+ // bytes long (the current code generates a 65 byte transaction instead to meet
916+ // standardness rule). It also tests the handling of selection failure where we selected
917+ // coins which were insufficient once the OP_RETURN output was added, causing us to need to
918+ // select coins again with additional weight.
919+
920+ // Tx 18032ad172a5f28fa6e16392d6cc57ea47895781434ce15d03766cc47a955fb9
921+ let commitment_tx_bytes = Vec :: < u8 > :: from_hex ( "02000000000101cc6b0a9dd84b52c07340fff6fab002fc37b4bdccfdce9f39c5ec8391a56b652907000000009b948b80044a01000000000000220020b4182433fdfdfbf894897c98f84d92cec815cee222755ffd000ae091c9dadc2d4a01000000000000220020f83f7dbf90e2de325b5bb6bab0ae370151278c6964739242b2e7ce0cb68a5d81cb4a02000000000022002024add256b3dccee772610caef82a601045ab6f98fd6d5df608cc756b891ccfe63ffa490000000000220020894bf32b37906a643625e87131897c3714c71b3ac9b161862c9aa6c8d468b4c70400473044022060abd347bff2cca0212b660e6addff792b3356bd4a1b5b26672dc2e694c3c5f002202b40b7e346b494a7b1d048b4ec33ba99c90a09ab48eb1df64ccdc768066c865c014730440220554d8361e04dc0ee178dcb23d2d23f53ec7a1ae4312a5be76bd9e83ab8981f3d0220501f23ffb18cb81ccea72d30252f88d5e69fd28ba4992803d03c00d06fa8899e0147522102817f6ce189ab7114f89e8d5df58cdbbaf272dc8e71b92982d47456a0b6a0ceee2102c9b4d2f24aca54f65e13f4c83e2a8d8e877e12d3c71a76e81f28a5cabc652aa352ae626c7620" ) . unwrap ( ) ;
922+ let commitment_tx: Transaction = Readable :: read ( & mut Cursor :: new ( & commitment_tx_bytes) ) . unwrap ( ) ;
923+ let total_commitment_weight = commitment_tx. weight ( ) . to_wu ( ) + ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT ;
924+ let commitment_and_anchor_fee = 930 + 330 ;
925+ let op_return_weight = TxOut {
926+ value : Amount :: ZERO ,
927+ script_pubkey : ScriptBuf :: new_op_return ( & [ 0 ; 3 ] ) ,
928+ } . weight ( ) . to_wu ( ) ;
929+
930+ let broadcaster = TestBroadcaster :: new ( Network :: Testnet ) ;
931+ let source = TestCoinSelectionSource {
932+ expected_selects : Mutex :: new ( vec ! [
933+ ( total_commitment_weight, commitment_and_anchor_fee, 868 , CoinSelection { confirmed_utxos: Vec :: new( ) , change_output: None } ) ,
934+ ( total_commitment_weight + op_return_weight, commitment_and_anchor_fee, 868 , CoinSelection {
935+ confirmed_utxos: vec![ Utxo {
936+ outpoint: OutPoint { txid: Txid :: from_byte_array( [ 44 ; 32 ] ) , vout: 0 } ,
937+ output: TxOut { value: Amount :: from_sat( 200 ) , script_pubkey: ScriptBuf :: new( ) } ,
938+ satisfaction_weight: 5 , // Just the script_sig and witness lengths
939+ } ] ,
940+ change_output: None ,
941+ } )
942+ ] ) ,
943+ } ;
944+ let signer = KeysManager :: new ( & [ 42 ; 32 ] , 42 , 42 ) ;
945+ let logger = TestLogger :: new ( ) ;
946+ let handler = BumpTransactionEventHandler :: new ( & broadcaster, & source, & signer, & logger) ;
947+
948+ handler. handle_event ( & BumpTransactionEvent :: ChannelClose {
949+ channel_id : ChannelId ( [ 42 ; 32 ] ) ,
950+ counterparty_node_id : PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) ,
951+ claim_id : ClaimId ( [ 42 ; 32 ] ) ,
952+ package_target_feerate_sat_per_1000_weight : 868 ,
953+ commitment_tx_fee_satoshis : 930 ,
954+ commitment_tx,
955+ anchor_descriptor : AnchorDescriptor {
956+ channel_derivation_parameters : ChannelDerivationParameters {
957+ value_satoshis : 42_000_000 ,
958+ keys_id : [ 42 ; 32 ] ,
959+ transaction_parameters : ChannelTransactionParameters :: test_dummy ( ) ,
960+ } ,
961+ outpoint : OutPoint { txid : Txid :: from_byte_array ( [ 42 ; 32 ] ) , vout : 0 } ,
962+ } ,
963+ pending_htlcs : Vec :: new ( ) ,
964+ } ) ;
965+ }
966+ }
0 commit comments