@@ -656,25 +656,26 @@ impl PackageSolvingData {
656656 _ => { panic ! ( "API Error!" ) ; }
657657 }
658658 }
659- fn absolute_tx_timelock ( & self , current_height : u32 ) -> u32 {
660- // We use `current_height` as our default locktime to discourage fee sniping and because
661- // transactions with it always propagate.
662- let absolute_timelock = match self {
663- PackageSolvingData :: RevokedOutput ( _) => current_height,
664- PackageSolvingData :: RevokedHTLCOutput ( _) => current_height,
665- PackageSolvingData :: CounterpartyOfferedHTLCOutput ( _) => current_height,
666- PackageSolvingData :: CounterpartyReceivedHTLCOutput ( ref outp) => cmp:: max ( outp. htlc . cltv_expiry , current_height) ,
667- // HTLC timeout/success transactions rely on a fixed timelock due to the counterparty's
668- // signature.
659+ /// Some output types are locked with CHECKLOCKTIMEVERIFY and the spending transaction must
660+ /// have a minimum locktime, which is returned here.
661+ fn minimum_locktime ( & self ) -> Option < u32 > {
662+ match self {
663+ PackageSolvingData :: CounterpartyReceivedHTLCOutput ( ref outp) => Some ( outp. htlc . cltv_expiry ) ,
664+ _ => None ,
665+ }
666+ }
667+ /// Some output types are pre-signed in such a way that the spending transaction must have an
668+ /// exact locktime. This returns that locktime for such outputs.
669+ fn signed_locktime ( & self ) -> Option < u32 > {
670+ match self {
669671 PackageSolvingData :: HolderHTLCOutput ( ref outp) => {
670672 if outp. preimage . is_some ( ) {
671673 debug_assert_eq ! ( outp. cltv_expiry, 0 ) ;
672674 }
673- outp. cltv_expiry
675+ Some ( outp. cltv_expiry )
674676 } ,
675- PackageSolvingData :: HolderFundingOutput ( _) => current_height,
676- } ;
677- absolute_timelock
677+ _ => None ,
678+ }
678679 }
679680
680681 fn map_output_type_flags ( & self ) -> ( PackageMalleability , bool ) {
@@ -860,36 +861,23 @@ impl PackageTemplate {
860861 }
861862 amounts
862863 }
863- pub ( crate ) fn package_locktime ( & self , current_height : u32 ) -> u32 {
864- let locktime = self . inputs . iter ( ) . map ( |( _, outp) | outp. absolute_tx_timelock ( current_height) )
865- . max ( ) . expect ( "There must always be at least one output to spend in a PackageTemplate" ) ;
866-
867- // If we ever try to aggregate a `HolderHTLCOutput`s with another output type, we'll likely
868- // end up with an incorrect transaction locktime since the counterparty has included it in
869- // its HTLC signature. This should never happen unless we decide to aggregate outputs across
870- // different channel commitments.
871- #[ cfg( debug_assertions) ] {
872- if self . inputs . iter ( ) . any ( |( _, outp) |
873- if let PackageSolvingData :: HolderHTLCOutput ( outp) = outp {
874- outp. preimage . is_some ( )
875- } else {
876- false
877- }
878- ) {
879- debug_assert_eq ! ( locktime, 0 ) ;
880- } ;
881- for timeout_htlc_expiry in self . inputs . iter ( ) . filter_map ( |( _, outp) |
882- if let PackageSolvingData :: HolderHTLCOutput ( outp) = outp {
883- if outp. preimage . is_none ( ) {
884- Some ( outp. cltv_expiry )
885- } else { None }
886- } else { None }
887- ) {
888- debug_assert_eq ! ( locktime, timeout_htlc_expiry) ;
889- }
864+ fn signed_locktime ( & self ) -> Option < u32 > {
865+ let signed_locktime = self . inputs . iter ( ) . find_map ( |( _, outp) | outp. signed_locktime ( ) ) ;
866+ #[ cfg( debug_assertions) ]
867+ for ( _, outp) in & self . inputs {
868+ debug_assert ! ( outp. signed_locktime( ) . is_none( ) || outp. signed_locktime( ) == signed_locktime) ;
890869 }
870+ signed_locktime
871+ }
872+ pub ( crate ) fn package_locktime ( & self , current_height : u32 ) -> u32 {
873+ let minimum_locktime = self . inputs . iter ( ) . filter_map ( |( _, outp) | outp. minimum_locktime ( ) ) . max ( ) . unwrap_or ( 0 ) ;
891874
892- locktime
875+ if let Some ( signed_locktime) = self . signed_locktime ( ) {
876+ debug_assert ! ( signed_locktime >= minimum_locktime) ;
877+ signed_locktime
878+ } else {
879+ core:: cmp:: max ( current_height, minimum_locktime)
880+ }
893881 }
894882 pub ( crate ) fn package_weight ( & self , destination_script : & Script ) -> u64 {
895883 let mut inputs_weight = 0 ;
@@ -1214,7 +1202,7 @@ where
12141202 F :: Target : FeeEstimator ,
12151203{
12161204 // If old feerate inferior to actual one given back by Fee Estimator, use it to compute new fee...
1217- let ( new_fee, new_feerate) = if let Some ( ( new_fee, new_feerate) ) =
1205+ let ( new_fee, new_feerate) = if let Some ( ( new_fee, new_feerate) ) =
12181206 compute_fee_from_spent_amounts ( input_amounts, predicted_weight, conf_target, fee_estimator, logger)
12191207 {
12201208 match feerate_strategy {
0 commit comments