3838 // A BDK on-chain wallet.
3939 inner : Mutex < bdk:: Wallet < D > > ,
4040 // A cache storing the most recently retrieved fee rate estimations.
41- fee_rate_cache : Mutex < HashMap < ConfirmationTarget , FeeRate > > ,
41+ fee_rate_cache : RwLock < HashMap < ConfirmationTarget , FeeRate > > ,
4242 tokio_runtime : RwLock < Option < Arc < tokio:: runtime:: Runtime > > > ,
4343 logger : Arc < FilesystemLogger > ,
4444}
@@ -51,18 +51,26 @@ where
5151 blockchain : EsploraBlockchain , wallet : bdk:: Wallet < D > , logger : Arc < FilesystemLogger > ,
5252 ) -> Self {
5353 let inner = Mutex :: new ( wallet) ;
54- let fee_rate_cache = Mutex :: new ( HashMap :: new ( ) ) ;
54+ let fee_rate_cache = RwLock :: new ( HashMap :: new ( ) ) ;
5555 let tokio_runtime = RwLock :: new ( None ) ;
5656 Self { blockchain, inner, fee_rate_cache, tokio_runtime, logger }
5757 }
5858
5959 pub ( crate ) async fn sync ( & self ) -> Result < ( ) , Error > {
60+ match self . update_fee_estimates ( ) . await {
61+ Ok ( ( ) ) => ( ) ,
62+ Err ( e) => {
63+ log_error ! ( self . logger, "Fee estimation error: {}" , e) ;
64+ return Err ( e) ;
65+ }
66+ }
67+
6068 let sync_options = SyncOptions { progress : None } ;
6169 match self . inner . lock ( ) . unwrap ( ) . sync ( & self . blockchain , sync_options) . await {
6270 Ok ( ( ) ) => Ok ( ( ) ) ,
6371 Err ( e) => {
6472 log_error ! ( self . logger, "Wallet sync error: {}" , e) ;
65- Err ( e ) ?
73+ Err ( From :: from ( e ) )
6674 }
6775 }
6876 }
7583 * self . tokio_runtime . write ( ) . unwrap ( ) = None ;
7684 }
7785
86+ pub ( crate ) async fn update_fee_estimates ( & self ) -> Result < ( ) , Error > {
87+ let mut locked_fee_rate_cache = self . fee_rate_cache . write ( ) . unwrap ( ) ;
88+
89+ let confirmation_targets = vec ! [
90+ ConfirmationTarget :: Background ,
91+ ConfirmationTarget :: Normal ,
92+ ConfirmationTarget :: HighPriority ,
93+ ] ;
94+ for target in confirmation_targets {
95+ let num_blocks = num_blocks_from_conf_target ( target) ;
96+
97+ let est_fee_rate = self . blockchain . estimate_fee ( num_blocks) . await ;
98+
99+ match est_fee_rate {
100+ Ok ( rate) => {
101+ locked_fee_rate_cache. insert ( target, rate) ;
102+ log_trace ! (
103+ self . logger,
104+ "Fee rate estimation updated: {} sats/kwu" ,
105+ rate. fee_wu( 1000 )
106+ ) ;
107+ }
108+ Err ( e) => {
109+ log_error ! ( self . logger, "Failed to update fee rate estimation: {}" , e) ;
110+ }
111+ }
112+ }
113+ Ok ( ( ) )
114+ }
115+
78116 pub ( crate ) fn create_funding_transaction (
79117 & self , output_script : & Script , value_sats : u64 , confirmation_target : ConfirmationTarget ,
80118 ) -> Result < Transaction , Error > {
@@ -123,41 +161,12 @@ where
123161 }
124162
125163 fn estimate_fee_rate ( & self , confirmation_target : ConfirmationTarget ) -> FeeRate {
126- let mut locked_fee_rate_cache = self . fee_rate_cache . lock ( ) . unwrap ( ) ;
127- let num_blocks = num_blocks_from_conf_target ( confirmation_target) ;
164+ let locked_fee_rate_cache = self . fee_rate_cache . read ( ) . unwrap ( ) ;
128165
129166 // We'll fall back on this, if we really don't have any other information.
130167 let fallback_rate = fallback_fee_from_conf_target ( confirmation_target) ;
131168
132- let locked_runtime = self . tokio_runtime . read ( ) . unwrap ( ) ;
133- if locked_runtime. as_ref ( ) . is_none ( ) {
134- log_error ! ( self . logger, "Failed to update fee rate estimation: No runtime." ) ;
135- unreachable ! ( "Failed to broadcast transaction: No runtime." ) ;
136- }
137-
138- let est_fee_rate = tokio:: task:: block_in_place ( move || {
139- locked_runtime
140- . as_ref ( )
141- . unwrap ( )
142- . handle ( )
143- . block_on ( async move { self . blockchain . estimate_fee ( num_blocks) . await } )
144- } ) ;
145-
146- match est_fee_rate {
147- Ok ( rate) => {
148- locked_fee_rate_cache. insert ( confirmation_target, rate) ;
149- log_trace ! (
150- self . logger,
151- "Fee rate estimation updated: {} sats/kwu" ,
152- rate. fee_wu( 1000 )
153- ) ;
154- rate
155- }
156- Err ( e) => {
157- log_error ! ( self . logger, "Failed to update fee rate estimation: {}" , e) ;
158- * locked_fee_rate_cache. get ( & confirmation_target) . unwrap_or ( & fallback_rate)
159- }
160- }
169+ * locked_fee_rate_cache. get ( & confirmation_target) . unwrap_or ( & fallback_rate)
161170 }
162171}
163172
@@ -335,8 +344,8 @@ where
335344 self . wallet . get_new_address ( ) . expect ( "Failed to retrieve new address from wallet." ) ;
336345 match address. payload {
337346 bitcoin:: util:: address:: Payload :: WitnessProgram { version, program } => {
338- return ShutdownScript :: new_witness_program ( version, & program)
339- . expect ( "Invalid shutdown script." ) ;
347+ ShutdownScript :: new_witness_program ( version, & program)
348+ . expect ( "Invalid shutdown script." )
340349 }
341350 _ => panic ! ( "Tried to use a non-witness address. This must not ever happen." ) ,
342351 }
0 commit comments