@@ -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 ;
@@ -792,3 +793,107 @@ pub(crate) fn get_witnesses_weight(inputs: &[InputDescriptors]) -> usize {
792
793
}
793
794
tx_weight
794
795
}
796
+
797
+ /// Attempt to propose a bumping fee for a transaction from its spent output's values and predicted
798
+ /// weight. We start with the highest priority feerate returned by the node's fee estimator then
799
+ /// fall-back to lower priorities until we have enough value available to suck from.
800
+ ///
801
+ /// If the proposed fee is less than the available spent output's values, we return the proposed
802
+ /// fee and the corresponding updated feerate. If the proposed fee is equal or more than the
803
+ /// available spent output's values, we return nothing
804
+ fn compute_fee_from_spent_amounts < F : Deref , L : Deref > ( input_amounts : u64 , predicted_weight : usize , fee_estimator : & F , logger : & L ) -> Option < ( u64 , u64 ) >
805
+ where F :: Target : FeeEstimator ,
806
+ L :: Target : Logger ,
807
+ {
808
+ let mut updated_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: HighPriority ) as u64 ;
809
+ let mut fee = updated_feerate * ( predicted_weight as u64 ) / 1000 ;
810
+ if input_amounts <= fee {
811
+ updated_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: Normal ) as u64 ;
812
+ fee = updated_feerate * ( predicted_weight as u64 ) / 1000 ;
813
+ if input_amounts <= fee {
814
+ updated_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: Background ) as u64 ;
815
+ fee = updated_feerate * ( predicted_weight as u64 ) / 1000 ;
816
+ if input_amounts <= fee {
817
+ 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)" ,
818
+ fee, input_amounts) ;
819
+ None
820
+ } else {
821
+ log_warn ! ( logger, "Used low priority fee for on-chain punishment tx as high priority fee was more than the entire claim balance ({} sat)" ,
822
+ input_amounts) ;
823
+ Some ( ( fee, updated_feerate) )
824
+ }
825
+ } else {
826
+ log_warn ! ( logger, "Used medium priority fee for on-chain punishment tx as high priority fee was more than the entire claim balance ({} sat)" ,
827
+ input_amounts) ;
828
+ Some ( ( fee, updated_feerate) )
829
+ }
830
+ } else {
831
+ Some ( ( fee, updated_feerate) )
832
+ }
833
+ }
834
+
835
+ /// Attempt to propose a bumping fee for a transaction from its spent output's values and predicted
836
+ /// weight. If feerates proposed by the fee-estimator have been increasing since last fee-bumping
837
+ /// attempt, use them. Otherwise, blindly bump the feerate by 25% of the previous feerate. We also
838
+ /// verify that those bumping heuristics respect BIP125 rules 3) and 4) and if required adjust
839
+ /// the new fee to meet the RBF policy requirement.
840
+ fn feerate_bump < F : Deref , L : Deref > ( predicted_weight : usize , input_amounts : u64 , previous_feerate : u64 , fee_estimator : & F , logger : & L ) -> Option < ( u64 , u64 ) >
841
+ where F :: Target : FeeEstimator ,
842
+ L :: Target : Logger ,
843
+ {
844
+ // If old feerate inferior to actual one given back by Fee Estimator, use it to compute new fee...
845
+ let new_fee = if let Some ( ( new_fee, _) ) = compute_fee_from_spent_amounts ( input_amounts, predicted_weight, fee_estimator, logger) {
846
+ let updated_feerate = new_fee / ( predicted_weight as u64 * 1000 ) ;
847
+ if updated_feerate > previous_feerate {
848
+ new_fee
849
+ } else {
850
+ // ...else just increase the previous feerate by 25% (because that's a nice number)
851
+ let new_fee = previous_feerate * ( predicted_weight as u64 ) / 750 ;
852
+ if input_amounts <= new_fee {
853
+ log_trace ! ( logger, "Can't 25% bump new claiming tx, amount {} is too small" , input_amounts) ;
854
+ return None ;
855
+ }
856
+ new_fee
857
+ }
858
+ } else {
859
+ log_trace ! ( logger, "Can't new-estimation bump new claiming tx, amount {} is too small" , input_amounts) ;
860
+ return None ;
861
+ } ;
862
+
863
+ let previous_fee = previous_feerate * ( predicted_weight as u64 ) / 1000 ;
864
+ let min_relay_fee = MIN_RELAY_FEE_SAT_PER_1000_WEIGHT * ( predicted_weight as u64 ) / 1000 ;
865
+ // BIP 125 Opt-in Full Replace-by-Fee Signaling
866
+ // * 3. The replacement transaction pays an absolute fee of at least the sum paid by the original transactions.
867
+ // * 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.
868
+ let new_fee = if new_fee < previous_fee + min_relay_fee {
869
+ new_fee + previous_fee + min_relay_fee - new_fee
870
+ } else {
871
+ new_fee
872
+ } ;
873
+ Some ( ( new_fee, new_fee * 1000 / ( predicted_weight as u64 ) ) )
874
+ }
875
+
876
+ /// Deduce a new proposed fee from the claiming transaction output value.
877
+ /// If the new proposed fee is superior to the consumed outpoint's value, burn everything in miner's
878
+ /// fee to deter counterparties attacker.
879
+ 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 ) >
880
+ where F :: Target : FeeEstimator ,
881
+ L :: Target : Logger ,
882
+ {
883
+ // If old feerate is 0, first iteration of this claim, use normal fee calculation
884
+ if previous_feerate != 0 {
885
+ if let Some ( ( new_fee, feerate) ) = feerate_bump ( predicted_weight, input_amounts, previous_feerate, fee_estimator, logger) {
886
+ // If new computed fee is superior at the whole claimable amount burn all in fees
887
+ if new_fee > input_amounts {
888
+ return Some ( ( 0 , feerate) ) ;
889
+ } else {
890
+ return Some ( ( input_amounts - new_fee, feerate) ) ;
891
+ }
892
+ }
893
+ } else {
894
+ if let Some ( ( new_fee, feerate) ) = compute_fee_from_spent_amounts ( input_amounts, predicted_weight, fee_estimator, logger) {
895
+ return Some ( ( input_amounts - new_fee, feerate) ) ;
896
+ }
897
+ }
898
+ None
899
+ }
0 commit comments