@@ -656,25 +656,26 @@ impl PackageSolvingData {
656
656
_ => { panic ! ( "API Error!" ) ; }
657
657
}
658
658
}
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 {
669
671
PackageSolvingData :: HolderHTLCOutput ( ref outp) => {
670
672
if outp. preimage . is_some ( ) {
671
673
debug_assert_eq ! ( outp. cltv_expiry, 0 ) ;
672
674
}
673
- outp. cltv_expiry
675
+ Some ( outp. cltv_expiry )
674
676
} ,
675
- PackageSolvingData :: HolderFundingOutput ( _) => current_height,
676
- } ;
677
- absolute_timelock
677
+ _ => None ,
678
+ }
678
679
}
679
680
680
681
fn map_output_type_flags ( & self ) -> ( PackageMalleability , bool ) {
@@ -860,36 +861,23 @@ impl PackageTemplate {
860
861
}
861
862
amounts
862
863
}
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) ;
890
869
}
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 ) ;
891
874
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
+ }
893
881
}
894
882
pub ( crate ) fn package_weight ( & self , destination_script : & Script ) -> u64 {
895
883
let mut inputs_weight = 0 ;
@@ -1214,7 +1202,7 @@ where
1214
1202
F :: Target : FeeEstimator ,
1215
1203
{
1216
1204
// 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) ) =
1218
1206
compute_fee_from_spent_amounts ( input_amounts, predicted_weight, conf_target, fee_estimator, logger)
1219
1207
{
1220
1208
match feerate_strategy {
0 commit comments