@@ -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 ) {
@@ -863,36 +864,23 @@ impl PackageTemplate {
863
864
}
864
865
amounts
865
866
}
866
- pub ( crate ) fn package_locktime ( & self , current_height : u32 ) -> u32 {
867
- let locktime = self . inputs . iter ( ) . map ( |( _, outp) | outp. absolute_tx_timelock ( current_height) )
868
- . max ( ) . expect ( "There must always be at least one output to spend in a PackageTemplate" ) ;
869
-
870
- // If we ever try to aggregate a `HolderHTLCOutput`s with another output type, we'll likely
871
- // end up with an incorrect transaction locktime since the counterparty has included it in
872
- // its HTLC signature. This should never happen unless we decide to aggregate outputs across
873
- // different channel commitments.
874
- #[ cfg( debug_assertions) ] {
875
- if self . inputs . iter ( ) . any ( |( _, outp) |
876
- if let PackageSolvingData :: HolderHTLCOutput ( outp) = outp {
877
- outp. preimage . is_some ( )
878
- } else {
879
- false
880
- }
881
- ) {
882
- debug_assert_eq ! ( locktime, 0 ) ;
883
- } ;
884
- for timeout_htlc_expiry in self . inputs . iter ( ) . filter_map ( |( _, outp) |
885
- if let PackageSolvingData :: HolderHTLCOutput ( outp) = outp {
886
- if outp. preimage . is_none ( ) {
887
- Some ( outp. cltv_expiry )
888
- } else { None }
889
- } else { None }
890
- ) {
891
- debug_assert_eq ! ( locktime, timeout_htlc_expiry) ;
892
- }
867
+ fn signed_locktime ( & self ) -> Option < u32 > {
868
+ let signed_locktime = self . inputs . iter ( ) . find_map ( |( _, outp) | outp. signed_locktime ( ) ) ;
869
+ #[ cfg( debug_assertions) ]
870
+ for ( _, outp) in & self . inputs {
871
+ debug_assert ! ( outp. signed_locktime( ) . is_none( ) || outp. signed_locktime( ) == signed_locktime) ;
893
872
}
873
+ signed_locktime
874
+ }
875
+ pub ( crate ) fn package_locktime ( & self , current_height : u32 ) -> u32 {
876
+ let minimum_locktime = self . inputs . iter ( ) . filter_map ( |( _, outp) | outp. minimum_locktime ( ) ) . max ( ) . unwrap_or ( 0 ) ;
894
877
895
- locktime
878
+ if let Some ( signed_locktime) = self . signed_locktime ( ) {
879
+ debug_assert ! ( signed_locktime >= minimum_locktime) ;
880
+ signed_locktime
881
+ } else {
882
+ core:: cmp:: max ( current_height, minimum_locktime)
883
+ }
896
884
}
897
885
pub ( crate ) fn package_weight ( & self , destination_script : & Script ) -> u64 {
898
886
let mut inputs_weight = 0 ;
@@ -1217,7 +1205,7 @@ where
1217
1205
F :: Target : FeeEstimator ,
1218
1206
{
1219
1207
// If old feerate inferior to actual one given back by Fee Estimator, use it to compute new fee...
1220
- let ( new_fee, new_feerate) = if let Some ( ( new_fee, new_feerate) ) =
1208
+ let ( new_fee, new_feerate) = if let Some ( ( new_fee, new_feerate) ) =
1221
1209
compute_fee_from_spent_amounts ( input_amounts, predicted_weight, conf_target, fee_estimator, logger)
1222
1210
{
1223
1211
match feerate_strategy {
0 commit comments