38
38
// A BDK on-chain wallet.
39
39
inner : Mutex < bdk:: Wallet < D > > ,
40
40
// 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 > > ,
42
42
tokio_runtime : RwLock < Option < Arc < tokio:: runtime:: Runtime > > > ,
43
43
logger : Arc < FilesystemLogger > ,
44
44
}
@@ -51,18 +51,26 @@ where
51
51
blockchain : EsploraBlockchain , wallet : bdk:: Wallet < D > , logger : Arc < FilesystemLogger > ,
52
52
) -> Self {
53
53
let inner = Mutex :: new ( wallet) ;
54
- let fee_rate_cache = Mutex :: new ( HashMap :: new ( ) ) ;
54
+ let fee_rate_cache = RwLock :: new ( HashMap :: new ( ) ) ;
55
55
let tokio_runtime = RwLock :: new ( None ) ;
56
56
Self { blockchain, inner, fee_rate_cache, tokio_runtime, logger }
57
57
}
58
58
59
59
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
+
60
68
let sync_options = SyncOptions { progress : None } ;
61
69
match self . inner . lock ( ) . unwrap ( ) . sync ( & self . blockchain , sync_options) . await {
62
70
Ok ( ( ) ) => Ok ( ( ) ) ,
63
71
Err ( e) => {
64
72
log_error ! ( self . logger, "Wallet sync error: {}" , e) ;
65
- Err ( e ) ?
73
+ Err ( From :: from ( e ) )
66
74
}
67
75
}
68
76
}
75
83
* self . tokio_runtime . write ( ) . unwrap ( ) = None ;
76
84
}
77
85
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
+
78
116
pub ( crate ) fn create_funding_transaction (
79
117
& self , output_script : & Script , value_sats : u64 , confirmation_target : ConfirmationTarget ,
80
118
) -> Result < Transaction , Error > {
@@ -123,41 +161,12 @@ where
123
161
}
124
162
125
163
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 ( ) ;
128
165
129
166
// We'll fall back on this, if we really don't have any other information.
130
167
let fallback_rate = fallback_fee_from_conf_target ( confirmation_target) ;
131
168
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)
161
170
}
162
171
}
163
172
@@ -335,8 +344,8 @@ where
335
344
self . wallet . get_new_address ( ) . expect ( "Failed to retrieve new address from wallet." ) ;
336
345
match address. payload {
337
346
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." )
340
349
}
341
350
_ => panic ! ( "Tried to use a non-witness address. This must not ever happen." ) ,
342
351
}
0 commit comments