@@ -25,6 +25,7 @@ use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, HTLC_OUTPUT_IN_COMM
25
25
use ln:: chan_utils;
26
26
use ln:: msgs:: DecodeError ;
27
27
use ln:: onchaintx:: OnchainTxHandler ;
28
+ use chain:: chaininterface:: { FeeEstimator , ConfirmationTarget , MIN_RELAY_FEE_SAT_PER_1000_WEIGHT } ;
28
29
use chain:: keysinterface:: Sign ;
29
30
use util:: byte_utils;
30
31
use util:: logger:: Logger ;
@@ -821,3 +822,104 @@ pub(crate) fn get_witnesses_weight(inputs: &[InputDescriptors]) -> usize {
821
822
}
822
823
tx_weight
823
824
}
825
+
826
+ /// Attempt to propose a fee based on consumed outpoints's values and predicted weight of the claiming
827
+ /// transaction. We start with the highest priority feerate returned by the node's fee estimator
828
+ /// then fall-back to lower priorities until we have enough value available to suck from.
829
+ /// If the proposed fee is more than the claimable balance, we return None
830
+ fn subtract_high_prio_fee < F : Deref , L : Deref > ( input_amounts : u64 , predicted_weight : usize , fee_estimator : & F , logger : & L ) -> Option < ( u64 , u64 ) >
831
+ where F :: Target : FeeEstimator ,
832
+ L :: Target : Logger ,
833
+ {
834
+ let mut updated_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: HighPriority ) as u64 ;
835
+ let mut fee = updated_feerate * ( predicted_weight as u64 ) / 1000 ;
836
+ if input_amounts <= fee {
837
+ updated_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: Normal ) as u64 ;
838
+ fee = updated_feerate * ( predicted_weight as u64 ) / 1000 ;
839
+ if input_amounts <= fee {
840
+ updated_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: Background ) as u64 ;
841
+ fee = updated_feerate * ( predicted_weight as u64 ) / 1000 ;
842
+ if input_amounts <= fee {
843
+ 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)" ,
844
+ fee, input_amounts) ;
845
+ None
846
+ } else {
847
+ log_warn ! ( logger, "Used low priority fee for on-chain punishment tx as high priority fee was more than the entire claim balance ({} sat)" ,
848
+ input_amounts) ;
849
+ Some ( ( fee, updated_feerate) )
850
+ }
851
+ } else {
852
+ log_warn ! ( logger, "Used medium priority fee for on-chain punishment tx as high priority fee was more than the entire claim balance ({} sat)" ,
853
+ input_amounts) ;
854
+ Some ( ( fee, updated_feerate) )
855
+ }
856
+ } else {
857
+ Some ( ( fee, updated_feerate) )
858
+ }
859
+ }
860
+
861
+ /// Attempt to propose a bumping fee based on consumed outpoint's value and predicted weight of the
862
+ /// claiming transaction. If feerates proposed by the fee-estimator have been increasing since last
863
+ /// fee-bumping attempt, use them. Otherwise, blindly bump the feerate by 25% of the previous
864
+ /// feerate.
865
+ /// We also verify that those bumping heuristics respect BIP125 rules 3) and 4) and if required
866
+ /// adjust the new fee to meet the RBF policy requirement.
867
+ fn feerate_bump < F : Deref , L : Deref > ( predicted_weight : usize , input_amounts : u64 , previous_feerate : u64 , fee_estimator : & F , logger : & L ) -> Option < ( u64 , u64 ) >
868
+ where F :: Target : FeeEstimator ,
869
+ L :: Target : Logger ,
870
+ {
871
+ // If old feerate inferior to actual one given back by Fee Estimator, use it to compute new fee...
872
+ let new_fee = if previous_feerate < fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: HighPriority ) as u64 {
873
+ if let Some ( ( new_fee, _) ) = subtract_high_prio_fee ( input_amounts, predicted_weight, fee_estimator, logger) {
874
+ new_fee
875
+ } else {
876
+ log_trace ! ( logger, "Can't new-estimation bump new claiming tx, amount {} is too small" , input_amounts) ;
877
+ return None ;
878
+ }
879
+ // ...else just increase the previous feerate by 25% (because that's a nice number)
880
+ } else {
881
+ let fee = previous_feerate * ( predicted_weight as u64 ) / 750 ;
882
+ if input_amounts <= fee {
883
+ log_trace ! ( logger, "Can't 25% bump new claiming tx, amount {} is too small" , input_amounts) ;
884
+ return None ;
885
+ }
886
+ fee
887
+ } ;
888
+
889
+ let previous_fee = previous_feerate * ( predicted_weight as u64 ) / 1000 ;
890
+ let min_relay_fee = MIN_RELAY_FEE_SAT_PER_1000_WEIGHT * ( predicted_weight as u64 ) / 1000 ;
891
+ // BIP 125 Opt-in Full Replace-by-Fee Signaling
892
+ // * 3. The replacement transaction pays an absolute fee of at least the sum paid by the original transactions.
893
+ // * 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.
894
+ let new_fee = if new_fee < previous_fee + min_relay_fee {
895
+ new_fee + previous_fee + min_relay_fee - new_fee
896
+ } else {
897
+ new_fee
898
+ } ;
899
+ Some ( ( new_fee, new_fee * 1000 / ( predicted_weight as u64 ) ) )
900
+ }
901
+
902
+ /// Deduce a new proposed fee from the claiming transaction output value.
903
+ /// If the new proposed fee is superior to the consumed outpoint's value, burn everything in miner's
904
+ /// fee to deter counterparties attacker.
905
+ 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 ) >
906
+ where F :: Target : FeeEstimator ,
907
+ L :: Target : Logger ,
908
+ {
909
+ // If old feerate is 0, first iteration of this claim, use normal fee calculation
910
+ if previous_feerate != 0 {
911
+ if let Some ( ( new_fee, feerate) ) = feerate_bump ( predicted_weight, input_amounts, previous_feerate, fee_estimator, logger) {
912
+ // If new computed fee is superior at the whole claimable amount burn all in fees
913
+ if new_fee > input_amounts {
914
+ return Some ( ( 0 , feerate) ) ;
915
+ } else {
916
+ return Some ( ( input_amounts - new_fee, feerate) ) ;
917
+ }
918
+ }
919
+ } else {
920
+ if let Some ( ( new_fee, feerate) ) = subtract_high_prio_fee ( input_amounts, predicted_weight, fee_estimator, logger) {
921
+ return Some ( ( input_amounts - new_fee, feerate) ) ;
922
+ }
923
+ }
924
+ None
925
+ }
0 commit comments