26
26
// A BDK on-chain wallet.
27
27
inner : Mutex < bdk:: Wallet < D > > ,
28
28
// A cache storing the most recently retrieved fee rate estimations.
29
- fee_rate_cache : Mutex < HashMap < ConfirmationTarget , FeeRate > > ,
29
+ fee_rate_cache : RwLock < HashMap < ConfirmationTarget , FeeRate > > ,
30
30
tokio_runtime : RwLock < Option < Arc < tokio:: runtime:: Runtime > > > ,
31
31
logger : Arc < FilesystemLogger > ,
32
32
}
@@ -39,18 +39,26 @@ where
39
39
blockchain : EsploraBlockchain , wallet : bdk:: Wallet < D > , logger : Arc < FilesystemLogger > ,
40
40
) -> Self {
41
41
let inner = Mutex :: new ( wallet) ;
42
- let fee_rate_cache = Mutex :: new ( HashMap :: new ( ) ) ;
42
+ let fee_rate_cache = RwLock :: new ( HashMap :: new ( ) ) ;
43
43
let tokio_runtime = RwLock :: new ( None ) ;
44
44
Self { blockchain, inner, fee_rate_cache, tokio_runtime, logger }
45
45
}
46
46
47
47
pub ( crate ) async fn sync ( & self ) -> Result < ( ) , Error > {
48
+ match self . update_fee_estimates ( ) . await {
49
+ Ok ( ( ) ) => ( ) ,
50
+ Err ( e) => {
51
+ log_error ! ( self . logger, "Fee estimation error: {}" , e) ;
52
+ return Err ( e) ;
53
+ }
54
+ }
55
+
48
56
let sync_options = SyncOptions { progress : None } ;
49
57
match self . inner . lock ( ) . unwrap ( ) . sync ( & self . blockchain , sync_options) . await {
50
58
Ok ( ( ) ) => Ok ( ( ) ) ,
51
59
Err ( e) => {
52
60
log_error ! ( self . logger, "Wallet sync error: {}" , e) ;
53
- Err ( e ) ?
61
+ Err ( From :: from ( e ) )
54
62
}
55
63
}
56
64
}
63
71
* self . tokio_runtime . write ( ) . unwrap ( ) = None ;
64
72
}
65
73
74
+ pub ( crate ) async fn update_fee_estimates ( & self ) -> Result < ( ) , Error > {
75
+ let mut locked_fee_rate_cache = self . fee_rate_cache . write ( ) . unwrap ( ) ;
76
+
77
+ let confirmation_targets = vec ! [
78
+ ConfirmationTarget :: Background ,
79
+ ConfirmationTarget :: Normal ,
80
+ ConfirmationTarget :: HighPriority ,
81
+ ] ;
82
+ for target in confirmation_targets {
83
+ let num_blocks = num_blocks_from_conf_target ( target) ;
84
+
85
+ let est_fee_rate = self . blockchain . estimate_fee ( num_blocks) . await ;
86
+
87
+ match est_fee_rate {
88
+ Ok ( rate) => {
89
+ locked_fee_rate_cache. insert ( target, rate) ;
90
+ log_trace ! (
91
+ self . logger,
92
+ "Fee rate estimation updated: {} sats/kwu" ,
93
+ rate. fee_wu( 1000 )
94
+ ) ;
95
+ }
96
+ Err ( e) => {
97
+ log_error ! ( self . logger, "Failed to update fee rate estimation: {}" , e) ;
98
+ }
99
+ }
100
+ }
101
+ Ok ( ( ) )
102
+ }
103
+
66
104
pub ( crate ) fn create_funding_transaction (
67
105
& self , output_script : & Script , value_sats : u64 , confirmation_target : ConfirmationTarget ,
68
106
) -> Result < Transaction , Error > {
@@ -111,41 +149,12 @@ where
111
149
}
112
150
113
151
fn estimate_fee_rate ( & self , confirmation_target : ConfirmationTarget ) -> FeeRate {
114
- let mut locked_fee_rate_cache = self . fee_rate_cache . lock ( ) . unwrap ( ) ;
115
- let num_blocks = num_blocks_from_conf_target ( confirmation_target) ;
152
+ let locked_fee_rate_cache = self . fee_rate_cache . read ( ) . unwrap ( ) ;
116
153
117
154
// We'll fall back on this, if we really don't have any other information.
118
155
let fallback_rate = fallback_fee_from_conf_target ( confirmation_target) ;
119
156
120
- let locked_runtime = self . tokio_runtime . read ( ) . unwrap ( ) ;
121
- if locked_runtime. as_ref ( ) . is_none ( ) {
122
- log_error ! ( self . logger, "Failed to update fee rate estimation: No runtime." ) ;
123
- unreachable ! ( "Failed to broadcast transaction: No runtime." ) ;
124
- }
125
-
126
- let est_fee_rate = tokio:: task:: block_in_place ( move || {
127
- locked_runtime
128
- . as_ref ( )
129
- . unwrap ( )
130
- . handle ( )
131
- . block_on ( async move { self . blockchain . estimate_fee ( num_blocks) . await } )
132
- } ) ;
133
-
134
- match est_fee_rate {
135
- Ok ( rate) => {
136
- locked_fee_rate_cache. insert ( confirmation_target, rate) ;
137
- log_trace ! (
138
- self . logger,
139
- "Fee rate estimation updated: {} sats/kwu" ,
140
- rate. fee_wu( 1000 )
141
- ) ;
142
- rate
143
- }
144
- Err ( e) => {
145
- log_error ! ( self . logger, "Failed to update fee rate estimation: {}" , e) ;
146
- * locked_fee_rate_cache. get ( & confirmation_target) . unwrap_or ( & fallback_rate)
147
- }
148
- }
157
+ * locked_fee_rate_cache. get ( & confirmation_target) . unwrap_or ( & fallback_rate)
149
158
}
150
159
}
151
160
0 commit comments