@@ -19,7 +19,7 @@ use lightning_block_sync::rpc::RpcClient;
1919use  lightning_block_sync:: { 
2020    AsyncBlockSourceResult ,  BlockHeaderData ,  BlockSource , 
2121} ; 
22- use  tokio:: runtime :: Handle ; 
22+ use  tokio:: task :: JoinHandle ; 
2323use  tokio:: time; 
2424use  tracing:: { debug,  error} ; 
2525
@@ -28,78 +28,44 @@ mod types;
2828pub  use  types:: * ; 
2929
3030const  POLL_FEE_ESTIMATE_INTERVAL :  Duration  = Duration :: from_secs ( 60 ) ; 
31+ /// The minimum feerate we are allowed to send, as specified by LDK. 
32+ const  MIN_FEERATE :  u32  = 253 ; 
3133
3234pub  struct  LexeBitcoind  { 
33-     bitcoind_rpc_client :  Arc < RpcClient > , 
34-     host :  String , 
35-     port :  u16 , 
36-     rpc_user :  String , 
37-     rpc_password :  String , 
35+     rpc_client :  Arc < RpcClient > , 
3836    background_fees :  Arc < AtomicU32 > , 
3937    normal_fees :  Arc < AtomicU32 > , 
4038    high_prio_fees :  Arc < AtomicU32 > , 
41-     handle :  Handle , 
42- } 
43- 
44- #[ derive( Clone ,  Eq ,  Hash ,  PartialEq ) ]  
45- pub  enum  Target  { 
46-     Background , 
47-     Normal , 
48-     HighPriority , 
49- } 
50- 
51- impl  BlockSource  for  & LexeBitcoind  { 
52-     fn  get_header < ' a > ( 
53-         & ' a  self , 
54-         header_hash :  & ' a  BlockHash , 
55-         height_hint :  Option < u32 > , 
56-     )  -> AsyncBlockSourceResult < ' a ,  BlockHeaderData >  { 
57-         Box :: pin ( async  move  { 
58-             self . bitcoind_rpc_client 
59-                 . get_header ( header_hash,  height_hint) 
60-                 . await 
61-         } ) 
62-     } 
63- 
64-     fn  get_block < ' a > ( 
65-         & ' a  self , 
66-         header_hash :  & ' a  BlockHash , 
67-     )  -> AsyncBlockSourceResult < ' a ,  Block >  { 
68-         Box :: pin ( async  move  { 
69-             self . bitcoind_rpc_client . get_block ( header_hash) . await 
70-         } ) 
71-     } 
72- 
73-     fn  get_best_block ( 
74-         & self , 
75-     )  -> AsyncBlockSourceResult < ( BlockHash ,  Option < u32 > ) >  { 
76-         Box :: pin ( async  move  {  self . bitcoind_rpc_client . get_best_block ( ) . await  } ) 
77-     } 
7839} 
7940
80- /// The minimum feerate we are allowed to send, as specify by LDK. 
81- const  MIN_FEERATE :  u32  = 253 ; 
82- 
8341impl  LexeBitcoind  { 
8442    pub  async  fn  init ( 
8543        bitcoind_rpc :  BitcoindRpcInfo , 
8644        network :  Network , 
87-     )  -> anyhow:: Result < Arc < Self > >  { 
88-         debug ! ( %network,  "initializing bitcoind client" ) ; 
89- 
90-         let  client = LexeBitcoind :: new ( 
91-             bitcoind_rpc. host , 
92-             bitcoind_rpc. port , 
93-             bitcoind_rpc. username , 
94-             bitcoind_rpc. password , 
95-             Handle :: current ( ) , 
96-         ) 
97-         . await 
98-         . context ( "Failed to connect to bitcoind client" ) ?; 
99-         let  client = Arc :: new ( client) ; 
100- 
101-         // Check that the bitcoind we've connected to is running the network we 
102-         // expect 
45+     )  -> anyhow:: Result < Self >  { 
46+         debug ! ( %network,  "Initializing bitcoind client" ) ; 
47+ 
48+         let  http_endpoint = HttpEndpoint :: for_host ( bitcoind_rpc. host . clone ( ) ) 
49+             . with_port ( bitcoind_rpc. port ) ; 
50+         let  credentials = bitcoind_rpc. base64_credentials ( ) ; 
51+         let  rpc_client = RpcClient :: new ( & credentials,  http_endpoint) 
52+             . context ( "Could not initialize RPC client" ) ?; 
53+         let  rpc_client = Arc :: new ( rpc_client) ; 
54+ 
55+         let  background_fees = Arc :: new ( AtomicU32 :: new ( MIN_FEERATE ) ) ; 
56+         let  normal_fees = Arc :: new ( AtomicU32 :: new ( 2000 ) ) ; 
57+         let  high_prio_fees = Arc :: new ( AtomicU32 :: new ( 5000 ) ) ; 
58+ 
59+         let  client = Self  { 
60+             rpc_client, 
61+             background_fees, 
62+             normal_fees, 
63+             high_prio_fees, 
64+         } ; 
65+ 
66+         // Make an initial test call to check that the RPC client is working 
67+         // correctly, and also check that the bitcoind we've connected to is 
68+         // running the network we expect 
10369        let  bitcoind_chain = client
10470            . get_blockchain_info ( ) 
10571            . await 
@@ -124,70 +90,19 @@ impl LexeBitcoind {
12490        Ok ( client) 
12591    } 
12692
127-     // A runtime handle has to be passed in explicitly, otherwise these fns may 
128-     // panic when called from the (non-Tokio) background processor thread 
129-     async  fn  new ( 
130-         host :  String , 
131-         port :  u16 , 
132-         rpc_user :  String , 
133-         rpc_password :  String , 
134-         handle :  Handle , 
135-     )  -> std:: io:: Result < Self >  { 
136-         let  http_endpoint =
137-             HttpEndpoint :: for_host ( host. clone ( ) ) . with_port ( port) ; 
138-         let  rpc_credentials = base64:: encode ( format ! ( 
139-             "{}:{}" , 
140-             rpc_user. clone( ) , 
141-             rpc_password. clone( ) 
142-         ) ) ; 
143-         let  bitcoind_rpc_client =
144-             RpcClient :: new ( & rpc_credentials,  http_endpoint) ?; 
145-         let  _dummy = bitcoind_rpc_client
146-             . call_method :: < BlockchainInfo > ( "getblockchaininfo" ,  & [ ] ) 
147-             . await 
148-             . map_err ( |_| { 
149-                 std:: io:: Error :: new ( std:: io:: ErrorKind :: PermissionDenied , 
150-                 "Failed to make initial call to bitcoind - please check your RPC user/password and access settings" ) 
151-             } ) ?; 
152- 
153-         let  background_fees = Arc :: new ( AtomicU32 :: new ( MIN_FEERATE ) ) ; 
154-         let  normal_fees = Arc :: new ( AtomicU32 :: new ( 2000 ) ) ; 
155-         let  high_prio_fees = Arc :: new ( AtomicU32 :: new ( 5000 ) ) ; 
93+     pub  fn  spawn_refresh_fees_task ( & self )  -> JoinHandle < ( ) >  { 
94+         let  rpc_client = self . rpc_client . clone ( ) ; 
95+         let  background_fees = self . background_fees . clone ( ) ; 
96+         let  normal_fees = self . normal_fees . clone ( ) ; 
97+         let  high_prio_fees = self . high_prio_fees . clone ( ) ; 
15698
157-         let  client = Self  { 
158-             bitcoind_rpc_client :  Arc :: new ( bitcoind_rpc_client) , 
159-             host, 
160-             port, 
161-             rpc_user, 
162-             rpc_password, 
163-             background_fees, 
164-             normal_fees, 
165-             high_prio_fees, 
166-             handle :  handle. clone ( ) , 
167-         } ; 
168-         client. poll_for_fee_estimates ( 
169-             client. background_fees . clone ( ) , 
170-             client. normal_fees . clone ( ) , 
171-             client. high_prio_fees . clone ( ) , 
172-             client. bitcoind_rpc_client . clone ( ) , 
173-         ) ; 
174-         Ok ( client) 
175-     } 
176- 
177-     fn  poll_for_fee_estimates ( 
178-         & self , 
179-         background_fees :  Arc < AtomicU32 > , 
180-         normal_fees :  Arc < AtomicU32 > , 
181-         high_prio_fees :  Arc < AtomicU32 > , 
182-         rpc_client :  Arc < RpcClient > , 
183-     )  { 
184-         self . handle . spawn ( async  move  { 
99+         tokio:: spawn ( async  move  { 
185100            let  mut  poll_interval = time:: interval ( POLL_FEE_ESTIMATE_INTERVAL ) ; 
186101
187102            loop  { 
188103                poll_interval. tick ( ) . await ; 
189104
190-                 let  poll_res = Self :: poll_for_fee_estimates_fallible ( 
105+                 let  poll_res = Self :: refresh_fees ( 
191106                    background_fees. as_ref ( ) , 
192107                    normal_fees. as_ref ( ) , 
193108                    high_prio_fees. as_ref ( ) , 
@@ -202,10 +117,10 @@ impl LexeBitcoind {
202117                    } 
203118                } 
204119            } 
205-         } ) ; 
120+         } ) 
206121    } 
207122
208-     async  fn  poll_for_fee_estimates_fallible ( 
123+     async  fn  refresh_fees ( 
209124        background_fees :  & AtomicU32 , 
210125        normal_fees :  & AtomicU32 , 
211126        high_prio_fees :  & AtomicU32 , 
@@ -267,23 +182,12 @@ impl LexeBitcoind {
267182        Ok ( ( ) ) 
268183    } 
269184
270-     pub  fn  get_new_rpc_client ( & self )  -> std:: io:: Result < RpcClient >  { 
271-         let  http_endpoint =
272-             HttpEndpoint :: for_host ( self . host . clone ( ) ) . with_port ( self . port ) ; 
273-         let  rpc_credentials = base64:: encode ( format ! ( 
274-             "{}:{}" , 
275-             self . rpc_user. clone( ) , 
276-             self . rpc_password. clone( ) 
277-         ) ) ; 
278-         RpcClient :: new ( & rpc_credentials,  http_endpoint) 
279-     } 
280- 
281185    pub  async  fn  create_raw_transaction ( 
282186        & self , 
283187        outputs :  Vec < HashMap < String ,  f64 > > , 
284188    )  -> anyhow:: Result < RawTx >  { 
285189        let  outputs_json = serde_json:: json!( outputs) ; 
286-         self . bitcoind_rpc_client 
190+         self . rpc_client 
287191            . call_method :: < RawTx > ( 
288192                "createrawtransaction" , 
289193                & [ serde_json:: json!( [ ] ) ,  outputs_json] , 
@@ -312,7 +216,7 @@ impl LexeBitcoind {
312216            // the same node. 
313217            "replaceable" :  false , 
314218        } ) ; 
315-         self . bitcoind_rpc_client 
219+         self . rpc_client 
316220            . call_method ( "fundrawtransaction" ,  & [ raw_tx_json,  options] ) 
317221            . await 
318222            . context ( "fundrawtransaction RPC call failed" ) 
@@ -323,7 +227,7 @@ impl LexeBitcoind {
323227        raw_tx :  RawTx , 
324228    )  -> anyhow:: Result < Txid >  { 
325229        let  raw_tx_json = serde_json:: json!( raw_tx. 0 ) ; 
326-         self . bitcoind_rpc_client 
230+         self . rpc_client 
327231            . call_method :: < Txid > ( "sendrawtransaction" ,  & [ raw_tx_json] ) 
328232            . await 
329233            . context ( "sesndrawtransaction RPC call failed" ) 
@@ -334,7 +238,7 @@ impl LexeBitcoind {
334238        tx_hex :  String , 
335239    )  -> anyhow:: Result < SignedTx >  { 
336240        let  tx_hex_json = serde_json:: json!( tx_hex) ; 
337-         self . bitcoind_rpc_client 
241+         self . rpc_client 
338242            . call_method ( "signrawtransactionwithwallet" ,  & [ tx_hex_json] ) 
339243            . await 
340244            . context ( "signrawtransactionwithwallet RPC call failed" ) 
@@ -343,7 +247,7 @@ impl LexeBitcoind {
343247    pub  async  fn  get_new_address ( & self )  -> anyhow:: Result < Address >  { 
344248        let  addr_args = vec ! [ serde_json:: json!( "LDK output address" ) ] ; 
345249        let  addr = self 
346-             . bitcoind_rpc_client 
250+             . rpc_client 
347251            . call_method :: < NewAddress > ( "getnewaddress" ,  & addr_args) 
348252            . await 
349253            . context ( "getnewaddress RPC call failed" ) ?; 
@@ -352,13 +256,38 @@ impl LexeBitcoind {
352256    } 
353257
354258    pub  async  fn  get_blockchain_info ( & self )  -> anyhow:: Result < BlockchainInfo >  { 
355-         self . bitcoind_rpc_client 
259+         self . rpc_client 
356260            . call_method :: < BlockchainInfo > ( "getblockchaininfo" ,  & [ ] ) 
357261            . await 
358262            . context ( "getblockchaininfo RPC call failed" ) 
359263    } 
360264} 
361265
266+ impl  BlockSource  for  & LexeBitcoind  { 
267+     fn  get_header < ' a > ( 
268+         & ' a  self , 
269+         header_hash :  & ' a  BlockHash , 
270+         height_hint :  Option < u32 > , 
271+     )  -> AsyncBlockSourceResult < ' a ,  BlockHeaderData >  { 
272+         Box :: pin ( async  move  { 
273+             self . rpc_client . get_header ( header_hash,  height_hint) . await 
274+         } ) 
275+     } 
276+ 
277+     fn  get_block < ' a > ( 
278+         & ' a  self , 
279+         header_hash :  & ' a  BlockHash , 
280+     )  -> AsyncBlockSourceResult < ' a ,  Block >  { 
281+         Box :: pin ( async  move  {  self . rpc_client . get_block ( header_hash) . await  } ) 
282+     } 
283+ 
284+     fn  get_best_block ( 
285+         & self , 
286+     )  -> AsyncBlockSourceResult < ( BlockHash ,  Option < u32 > ) >  { 
287+         Box :: pin ( async  move  {  self . rpc_client . get_best_block ( ) . await  } ) 
288+     } 
289+ } 
290+ 
362291impl  FeeEstimator  for  LexeBitcoind  { 
363292    fn  get_est_sat_per_1000_weight ( 
364293        & self , 
@@ -381,13 +310,13 @@ impl FeeEstimator for LexeBitcoind {
381310impl  BroadcasterInterface  for  LexeBitcoind  { 
382311    fn  broadcast_transaction ( & self ,  tx :  & Transaction )  { 
383312        debug ! ( "Broadcasting transaction" ) ; 
384-         let  bitcoind_rpc_client  = self . bitcoind_rpc_client . clone ( ) ; 
313+         let  rpc_client  = self . rpc_client . clone ( ) ; 
385314        let  tx_serialized = serde_json:: json!( encode:: serialize_hex( tx) ) ; 
386-         self . handle . spawn ( async  move  { 
315+         tokio :: spawn ( async  move  { 
387316            // This may error due to RL calling `broadcast_transaction` with the 
388317            // same transaction multiple times, but the error is 
389318            // safe to ignore. 
390-             match  bitcoind_rpc_client 
319+             match  rpc_client 
391320                . call_method :: < Txid > ( "sendrawtransaction" ,  & [ tx_serialized] ) 
392321                . await 
393322            { 
0 commit comments