7
7
8
8
mod bitcoind_rpc;
9
9
10
- use crate :: chain:: bitcoind_rpc:: { BitcoindRpcClient , BoundedHeaderCache , ChainListener } ;
10
+ use crate :: chain:: bitcoind_rpc:: {
11
+ BitcoindRpcClient , BoundedHeaderCache , ChainListener , FeeRateEstimationMode ,
12
+ } ;
11
13
use crate :: config:: {
12
14
Config , EsploraSyncConfig , BDK_CLIENT_CONCURRENCY , BDK_CLIENT_STOP_GAP ,
13
15
BDK_WALLET_SYNC_TIMEOUT_SECS , FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS , LDK_WALLET_SYNC_TIMEOUT_SECS ,
@@ -16,13 +18,14 @@ use crate::config::{
16
18
} ;
17
19
use crate :: fee_estimator:: {
18
20
apply_post_estimation_adjustments, get_all_conf_targets, get_num_block_defaults_for_target,
19
- OnchainFeeEstimator ,
21
+ ConfirmationTarget , OnchainFeeEstimator ,
20
22
} ;
21
23
use crate :: io:: utils:: write_node_metrics;
22
24
use crate :: logger:: { log_bytes, log_error, log_info, log_trace, FilesystemLogger , Logger } ;
23
25
use crate :: types:: { Broadcaster , ChainMonitor , ChannelManager , DynStore , Sweeper , Wallet } ;
24
26
use crate :: { Error , NodeMetrics } ;
25
27
28
+ use lightning:: chain:: chaininterface:: ConfirmationTarget as LdkConfirmationTarget ;
26
29
use lightning:: chain:: { Confirm , Filter , Listen } ;
27
30
use lightning:: util:: ser:: Writeable ;
28
31
@@ -356,6 +359,13 @@ impl ChainSource {
356
359
chain_polling_interval
357
360
. set_missed_tick_behavior ( tokio:: time:: MissedTickBehavior :: Skip ) ;
358
361
362
+ let mut fee_rate_update_interval =
363
+ tokio:: time:: interval ( Duration :: from_secs ( CHAIN_POLLING_INTERVAL_SECS ) ) ;
364
+ // When starting up, we just blocked on updating, so skip the first tick.
365
+ fee_rate_update_interval. reset ( ) ;
366
+ fee_rate_update_interval
367
+ . set_missed_tick_behavior ( tokio:: time:: MissedTickBehavior :: Skip ) ;
368
+
359
369
// Start the polling loop.
360
370
loop {
361
371
tokio:: select! {
@@ -369,6 +379,9 @@ impl ChainSource {
369
379
_ = chain_polling_interval. tick( ) => {
370
380
let _ = self . poll_and_update_listeners( Arc :: clone( & channel_manager) , Arc :: clone( & chain_monitor) , Arc :: clone( & output_sweeper) ) . await ;
371
381
}
382
+ _ = fee_rate_update_interval. tick( ) => {
383
+ let _ = self . update_fee_rate_estimates( ) . await ;
384
+ }
372
385
}
373
386
}
374
387
} ,
@@ -805,7 +818,108 @@ impl ChainSource {
805
818
806
819
Ok ( ( ) )
807
820
} ,
808
- Self :: BitcoindRpc { .. } => todo ! ( ) ,
821
+ Self :: BitcoindRpc {
822
+ bitcoind_rpc_client,
823
+ fee_estimator,
824
+ kv_store,
825
+ logger,
826
+ node_metrics,
827
+ ..
828
+ } => {
829
+ macro_rules! get_fee_rate_update {
830
+ ( $estimation_fut: expr) => { {
831
+ tokio:: time:: timeout(
832
+ Duration :: from_secs( FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS ) ,
833
+ $estimation_fut,
834
+ )
835
+ . await
836
+ . map_err( |e| {
837
+ log_error!( logger, "Updating fee rate estimates timed out: {}" , e) ;
838
+ Error :: FeerateEstimationUpdateTimeout
839
+ } ) ?
840
+ . map_err( |e| {
841
+ log_error!( logger, "Failed to retrieve fee rate estimates: {}" , e) ;
842
+ Error :: FeerateEstimationUpdateFailed
843
+ } ) ?
844
+ } } ;
845
+ }
846
+ let confirmation_targets = get_all_conf_targets ( ) ;
847
+
848
+ let mut new_fee_rate_cache = HashMap :: with_capacity ( 10 ) ;
849
+ let now = Instant :: now ( ) ;
850
+ for target in confirmation_targets {
851
+ let fee_rate = match target {
852
+ ConfirmationTarget :: Lightning (
853
+ LdkConfirmationTarget :: MinAllowedAnchorChannelRemoteFee ,
854
+ ) => {
855
+ let estimation_fut = bitcoind_rpc_client. get_mempool_minimum_fee_rate ( ) ;
856
+ get_fee_rate_update ! ( estimation_fut)
857
+ } ,
858
+ ConfirmationTarget :: Lightning (
859
+ LdkConfirmationTarget :: MaximumFeeEstimate ,
860
+ ) => {
861
+ let num_blocks = get_num_block_defaults_for_target ( target) ;
862
+ let estimation_mode = FeeRateEstimationMode :: Conservative ;
863
+ let estimation_fut = bitcoind_rpc_client
864
+ . get_fee_estimate_for_target ( num_blocks, estimation_mode) ;
865
+ get_fee_rate_update ! ( estimation_fut)
866
+ } ,
867
+ ConfirmationTarget :: Lightning (
868
+ LdkConfirmationTarget :: UrgentOnChainSweep ,
869
+ ) => {
870
+ let num_blocks = get_num_block_defaults_for_target ( target) ;
871
+ let estimation_mode = FeeRateEstimationMode :: Conservative ;
872
+ let estimation_fut = bitcoind_rpc_client
873
+ . get_fee_estimate_for_target ( num_blocks, estimation_mode) ;
874
+ get_fee_rate_update ! ( estimation_fut)
875
+ } ,
876
+ _ => {
877
+ // Otherwise, we default to economical block-target estimate.
878
+ let num_blocks = get_num_block_defaults_for_target ( target) ;
879
+ let estimation_mode = FeeRateEstimationMode :: Economical ;
880
+ let estimation_fut = bitcoind_rpc_client
881
+ . get_fee_estimate_for_target ( num_blocks, estimation_mode) ;
882
+ get_fee_rate_update ! ( estimation_fut)
883
+ } ,
884
+ } ;
885
+
886
+ // LDK 0.0.118 introduced changes to the `ConfirmationTarget` semantics that
887
+ // require some post-estimation adjustments to the fee rates, which we do here.
888
+ let adjusted_fee_rate = apply_post_estimation_adjustments ( target, fee_rate) ;
889
+
890
+ new_fee_rate_cache. insert ( target, adjusted_fee_rate) ;
891
+
892
+ log_trace ! (
893
+ logger,
894
+ "Fee rate estimation updated for {:?}: {} sats/kwu" ,
895
+ target,
896
+ adjusted_fee_rate. to_sat_per_kwu( ) ,
897
+ ) ;
898
+ }
899
+
900
+ if fee_estimator. set_fee_rate_cache ( new_fee_rate_cache) {
901
+ // We only log if the values changed, as it might be very spammy otherwise.
902
+ log_info ! (
903
+ logger,
904
+ "Fee rate cache update finished in {}ms." ,
905
+ now. elapsed( ) . as_millis( )
906
+ ) ;
907
+ }
908
+
909
+ let unix_time_secs_opt =
910
+ SystemTime :: now ( ) . duration_since ( UNIX_EPOCH ) . ok ( ) . map ( |d| d. as_secs ( ) ) ;
911
+ {
912
+ let mut locked_node_metrics = node_metrics. write ( ) . unwrap ( ) ;
913
+ locked_node_metrics. latest_fee_rate_cache_update_timestamp = unix_time_secs_opt;
914
+ write_node_metrics (
915
+ & * locked_node_metrics,
916
+ Arc :: clone ( & kv_store) ,
917
+ Arc :: clone ( & logger) ,
918
+ ) ?;
919
+ }
920
+
921
+ Ok ( ( ) )
922
+ } ,
809
923
}
810
924
}
811
925
0 commit comments