@@ -24,6 +24,7 @@ use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment};
24
24
use ln:: chan_utils;
25
25
use ln:: msgs:: DecodeError ;
26
26
use ln:: onchaintx:: OnchainTxHandler ;
27
+ use chain:: chaininterface:: { FeeEstimator , ConfirmationTarget , MIN_RELAY_FEE_SAT_PER_1000_WEIGHT } ;
27
28
use chain:: keysinterface:: Sign ;
28
29
use util:: byte_utils;
29
30
use util:: logger:: Logger ;
@@ -769,3 +770,104 @@ impl Readable for PackageTemplate {
769
770
} )
770
771
}
771
772
}
773
+
774
+ /// Attempt to propose a fee based on consumed outpoints's values and predicted weight of the claiming
775
+ /// transaction. We start with the highest priority feerate returned by the node's fee estimator
776
+ /// then fall-back to lower priorities until we have enough value available to suck from.
777
+ /// If the proposed fee is more than the claimable balance, we return None
778
+ fn subtract_high_prio_fee < F : Deref , L : Deref > ( input_amounts : u64 , predicted_weight : usize , fee_estimator : & F , logger : & L ) -> Option < ( u64 , u64 ) >
779
+ where F :: Target : FeeEstimator ,
780
+ L :: Target : Logger ,
781
+ {
782
+ let mut updated_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: HighPriority ) as u64 ;
783
+ let mut fee = updated_feerate * ( predicted_weight as u64 ) / 1000 ;
784
+ if input_amounts <= fee {
785
+ updated_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: Normal ) as u64 ;
786
+ fee = updated_feerate * ( predicted_weight as u64 ) / 1000 ;
787
+ if input_amounts <= fee {
788
+ updated_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: Background ) as u64 ;
789
+ fee = updated_feerate * ( predicted_weight as u64 ) / 1000 ;
790
+ if input_amounts <= fee {
791
+ log_error ! ( logger, "Failed to generate an on-chain punishment tx as even low priority fee ({} sat) was more than the entire claim balance ({} sat)" ,
792
+ fee, input_amounts) ;
793
+ None
794
+ } else {
795
+ log_warn ! ( logger, "Used low priority fee for on-chain punishment tx as high priority fee was more than the entire claim balance ({} sat)" ,
796
+ input_amounts) ;
797
+ Some ( ( fee, updated_feerate) )
798
+ }
799
+ } else {
800
+ log_warn ! ( logger, "Used medium priority fee for on-chain punishment tx as high priority fee was more than the entire claim balance ({} sat)" ,
801
+ input_amounts) ;
802
+ Some ( ( fee, updated_feerate) )
803
+ }
804
+ } else {
805
+ Some ( ( fee, updated_feerate) )
806
+ }
807
+ }
808
+
809
+ /// Attempt to propose a bumping fee based on consumed outpoint's value and predicted weight of the
810
+ /// claiming transaction. If feerates proposed by the fee-estimator have been increasing since last
811
+ /// fee-bumping attempt, use them. Otherwise, blindly bump the feerate by 25% of the previous
812
+ /// feerate.
813
+ /// We also verify that those bumping heuristics respect BIP125 rules 3) and 4) and if required
814
+ /// adjust the new fee to meet the RBF policy requirement.
815
+ fn feerate_bump < F : Deref , L : Deref > ( predicted_weight : usize , input_amounts : u64 , previous_feerate : u64 , fee_estimator : & F , logger : & L ) -> Option < ( u64 , u64 ) >
816
+ where F :: Target : FeeEstimator ,
817
+ L :: Target : Logger ,
818
+ {
819
+ // If old feerate inferior to actual one given back by Fee Estimator, use it to compute new fee...
820
+ let new_fee = if previous_feerate < fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: HighPriority ) as u64 {
821
+ if let Some ( ( new_fee, _) ) = subtract_high_prio_fee ( input_amounts, predicted_weight, fee_estimator, logger) {
822
+ new_fee
823
+ } else {
824
+ log_trace ! ( logger, "Can't new-estimation bump new claiming tx, amount {} is too small" , input_amounts) ;
825
+ return None ;
826
+ }
827
+ // ...else just increase the previous feerate by 25% (because that's a nice number)
828
+ } else {
829
+ let fee = previous_feerate * ( predicted_weight as u64 ) / 750 ;
830
+ if input_amounts <= fee {
831
+ log_trace ! ( logger, "Can't 25% bump new claiming tx, amount {} is too small" , input_amounts) ;
832
+ return None ;
833
+ }
834
+ fee
835
+ } ;
836
+
837
+ let previous_fee = previous_feerate * ( predicted_weight as u64 ) / 1000 ;
838
+ let min_relay_fee = MIN_RELAY_FEE_SAT_PER_1000_WEIGHT * ( predicted_weight as u64 ) / 1000 ;
839
+ // BIP 125 Opt-in Full Replace-by-Fee Signaling
840
+ // * 3. The replacement transaction pays an absolute fee of at least the sum paid by the original transactions.
841
+ // * 4. The replacement transaction must also pay for its own bandwidth at or above the rate set by the node's minimum relay fee setting.
842
+ let new_fee = if new_fee < previous_fee + min_relay_fee {
843
+ new_fee + previous_fee + min_relay_fee - new_fee
844
+ } else {
845
+ new_fee
846
+ } ;
847
+ Some ( ( new_fee, new_fee * 1000 / ( predicted_weight as u64 ) ) )
848
+ }
849
+
850
+ /// Deduce a new proposed fee from the claiming transaction output value.
851
+ /// If the new proposed fee is superior to the consumed outpoint's value, burn everything in miner's
852
+ /// fee to deter counterparties attacker.
853
+ pub ( crate ) fn compute_output_value < F : Deref , L : Deref > ( predicted_weight : usize , input_amounts : u64 , previous_feerate : u64 , fee_estimator : & F , logger : & L ) -> Option < ( u64 , u64 ) >
854
+ where F :: Target : FeeEstimator ,
855
+ L :: Target : Logger ,
856
+ {
857
+ // If old feerate is 0, first iteration of this claim, use normal fee calculation
858
+ if previous_feerate != 0 {
859
+ if let Some ( ( new_fee, feerate) ) = feerate_bump ( predicted_weight, input_amounts, previous_feerate, fee_estimator, logger) {
860
+ // If new computed fee is superior at the whole claimable amount burn all in fees
861
+ if new_fee > input_amounts {
862
+ return Some ( ( 0 , feerate) ) ;
863
+ } else {
864
+ return Some ( ( input_amounts - new_fee, feerate) ) ;
865
+ }
866
+ }
867
+ } else {
868
+ if let Some ( ( new_fee, feerate) ) = subtract_high_prio_fee ( input_amounts, predicted_weight, fee_estimator, logger) {
869
+ return Some ( ( input_amounts - new_fee, feerate) ) ;
870
+ }
871
+ }
872
+ None
873
+ }
0 commit comments