@@ -12,10 +12,11 @@ use std::collections::HashMap;
12
12
use std:: fs:: File ;
13
13
use std:: iter:: FromIterator ;
14
14
use std:: path:: PathBuf ;
15
+ use std:: str:: FromStr ;
16
+ use std:: sync:: atomic;
15
17
use std:: { fmt, result} ;
16
18
17
19
use crate :: { bitcoin, deserialize_hex} ;
18
- use jsonrpc;
19
20
use serde;
20
21
use serde_json;
21
22
@@ -1195,7 +1196,10 @@ pub trait RpcApi: Sized {
1195
1196
1196
1197
/// Client implements a JSON-RPC client for the Bitcoin Core daemon or compatible APIs.
1197
1198
pub struct Client {
1198
- client : jsonrpc:: client:: Client ,
1199
+ client : reqwest:: blocking:: Client ,
1200
+ url : String ,
1201
+ auth : Auth ,
1202
+ nonce : atomic:: AtomicUsize ,
1199
1203
}
1200
1204
1201
1205
impl fmt:: Debug for Client {
@@ -1209,23 +1213,27 @@ impl Client {
1209
1213
///
1210
1214
/// Can only return [Err] when using cookie authentication.
1211
1215
pub fn new ( url : & str , auth : Auth ) -> Result < Self > {
1212
- let ( user, pass) = auth. get_user_pass ( ) ?;
1213
- jsonrpc:: client:: Client :: simple_http ( url, user, pass)
1214
- . map ( |client| Client {
1215
- client,
1216
- } )
1217
- . map_err ( |e| super :: error:: Error :: JsonRpc ( e. into ( ) ) )
1216
+ let client = reqwest:: blocking:: Client :: builder ( ) . build ( ) . map_err ( |e| super :: error:: Error :: Http ( e) ) ?;
1217
+ Ok ( Self {
1218
+ client,
1219
+ auth : auth,
1220
+ url : String :: from_str ( url) . unwrap ( ) ,
1221
+ nonce : atomic:: AtomicUsize :: new ( 1 ) ,
1222
+ } )
1218
1223
}
1219
1224
1220
1225
/// Create a new Client using the given [jsonrpc::Client].
1221
- pub fn from_jsonrpc ( client : jsonrpc :: client :: Client ) -> Client {
1226
+ pub fn from_reqwest ( client : reqwest :: blocking :: Client , url : & str ) -> Client {
1222
1227
Client {
1223
1228
client,
1229
+ url : String :: from_str ( url) . unwrap ( ) ,
1230
+ auth : Auth :: None ,
1231
+ nonce : atomic:: AtomicUsize :: new ( 1 ) ,
1224
1232
}
1225
1233
}
1226
1234
1227
1235
/// Get the underlying JSONRPC client.
1228
- pub fn get_jsonrpc_client ( & self ) -> & jsonrpc :: client :: Client {
1236
+ pub fn get_reqwest_client ( & self ) -> & reqwest :: blocking :: Client {
1229
1237
& self . client
1230
1238
}
1231
1239
}
@@ -1245,14 +1253,45 @@ impl RpcApi for Client {
1245
1253
} )
1246
1254
. map ( |a| a. map_err ( |e| Error :: Json ( e) ) )
1247
1255
. collect :: < Result < Vec < _ > > > ( ) ?;
1248
- let req = self . client . build_request ( & cmd, & raw_args) ;
1249
- if log_enabled ! ( Debug ) {
1250
- debug ! ( target: "bitcoincore_rpc" , "JSON-RPC request: {} {}" , cmd, serde_json:: Value :: from( args) ) ;
1256
+
1257
+ let nonce = self . nonce . fetch_add ( 1 , atomic:: Ordering :: Relaxed ) ;
1258
+ let body = jsonrpc:: Request {
1259
+ method : cmd,
1260
+ params : raw_args. as_slice ( ) ,
1261
+ id : serde_json:: Value :: from ( nonce) ,
1262
+ jsonrpc : Some ( "2.0" ) ,
1263
+ } ;
1264
+ let id = body. id . clone ( ) ;
1265
+ let mut request = self . client
1266
+ . post ( self . url . as_str ( ) )
1267
+ . body ( serde_json:: to_vec ( & body) ?) ;
1268
+
1269
+
1270
+ request = match & self . auth {
1271
+ Auth :: UserPass ( user, pass) => request. basic_auth ( user, Some ( pass) ) ,
1272
+ Auth :: CookieFile ( _) => {
1273
+ let ( user, pass) = self . auth . clone ( ) . get_user_pass ( ) ?;
1274
+ request. basic_auth ( user. unwrap ( ) , pass)
1275
+ }
1276
+ Auth :: None => request,
1277
+ } ;
1278
+
1279
+ let response = request. send ( ) ;
1280
+
1281
+ let response = response. map_err ( |e| Error :: Http ( e) ) ?;
1282
+ let buffer = response. bytes ( ) . unwrap ( ) ;
1283
+ let jsonrpc_response_maybe: Result < jsonrpc:: Response > = serde_json:: from_slice ( & buffer) . map_err ( |e| Error :: Json ( e) ) ;
1284
+ log_response ( cmd, & jsonrpc_response_maybe) ;
1285
+ let jsonrpc_response = jsonrpc_response_maybe?;
1286
+
1287
+ if jsonrpc_response. jsonrpc . is_some ( ) && jsonrpc_response. jsonrpc != Some ( From :: from ( "2.0" ) ) {
1288
+ return Err ( Error :: JsonRpc ( jsonrpc:: error:: Error :: VersionMismatch ) ) ;
1289
+ }
1290
+ if jsonrpc_response. id != id {
1291
+ return Err ( Error :: JsonRpc ( jsonrpc:: error:: Error :: NonceMismatch ) ) ;
1251
1292
}
1252
1293
1253
- let resp = self . client . send_request ( req) . map_err ( Error :: from) ;
1254
- log_response ( cmd, & resp) ;
1255
- Ok ( resp?. result ( ) ?)
1294
+ jsonrpc_response. result ( ) . map_err ( Error :: JsonRpc )
1256
1295
}
1257
1296
}
1258
1297
0 commit comments