Skip to content

Commit b96a757

Browse files
committed
use minreq instead of jsonrpc http implementation
1 parent bde02d7 commit b96a757

File tree

3 files changed

+59
-29
lines changed

3 files changed

+59
-29
lines changed

client/Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ bitcoincore-rpc-json = { version = "0.16.0", path = "../json" }
2323

2424
log = "0.4.5"
2525
jsonrpc = "0.13.0"
26-
26+
minreq = "2.6.0"
2727
# Used for deserialization of JSON.
2828
serde = "1"
29-
serde_json = "1"
29+
serde_json = {version = "1", features = ["raw_value"]}
30+
base64 = { version = "0.13.0" }

client/src/client.rs

+54-26
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ use std::collections::HashMap;
1212
use std::fs::File;
1313
use std::iter::FromIterator;
1414
use std::path::PathBuf;
15+
use std::str::FromStr;
16+
use std::sync::atomic;
1517
use std::{fmt, result};
1618

1719
use crate::{bitcoin, deserialize_hex};
18-
use jsonrpc;
1920
use serde;
2021
use serde_json;
2122

@@ -1195,12 +1196,14 @@ pub trait RpcApi: Sized {
11951196

11961197
/// Client implements a JSON-RPC client for the Bitcoin Core daemon or compatible APIs.
11971198
pub struct Client {
1198-
client: jsonrpc::client::Client,
1199+
url: String,
1200+
auth: Auth,
1201+
nonce: atomic::AtomicUsize,
11991202
}
12001203

12011204
impl fmt::Debug for Client {
12021205
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1203-
write!(f, "bitcoincore_rpc::Client({:?})", self.client)
1206+
write!(f, "bitcoincore_rpc::Client()")
12041207
}
12051208
}
12061209

@@ -1209,25 +1212,20 @@ impl Client {
12091212
///
12101213
/// Can only return [Err] when using cookie authentication.
12111214
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()))
1218-
}
1219-
1220-
/// Create a new Client using the given [jsonrpc::Client].
1221-
pub fn from_jsonrpc(client: jsonrpc::client::Client) -> Client {
1222-
Client {
1223-
client,
1224-
}
1215+
Ok(Self{
1216+
auth: auth,
1217+
url: String::from_str(url).unwrap(),
1218+
nonce: atomic::AtomicUsize::new(1),
1219+
})
12251220
}
1221+
}
12261222

1227-
/// Get the underlying JSONRPC client.
1228-
pub fn get_jsonrpc_client(&self) -> &jsonrpc::client::Client {
1229-
&self.client
1230-
}
1223+
fn auth_token(user: &String, password: &String) -> String {
1224+
let mut auth = String::new();
1225+
auth.push_str(user);
1226+
auth.push(':');
1227+
auth.push_str(password);
1228+
base64::encode(auth.as_bytes())
12311229
}
12321230

12331231
impl RpcApi for Client {
@@ -1245,14 +1243,44 @@ impl RpcApi for Client {
12451243
})
12461244
.map(|a| a.map_err(|e| Error::Json(e)))
12471245
.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));
1246+
1247+
let nonce = self.nonce.fetch_add(1, atomic::Ordering::Relaxed);
1248+
let body = jsonrpc::Request{
1249+
method: cmd,
1250+
params: raw_args.as_slice(),
1251+
id: serde_json::Value::from(nonce),
1252+
jsonrpc: Some("2.0"),
1253+
};
1254+
let id = body.id.clone();
1255+
1256+
let mut request = minreq::post(self.url.as_str())
1257+
.with_body(serde_json::to_vec(&body)?);
1258+
1259+
request = match &self.auth {
1260+
Auth::UserPass(user, pass) => request.with_header("Authorization", format!("Basic {}", auth_token(user, pass))),
1261+
Auth::CookieFile(_)=> {
1262+
let (user, pass) = self.auth.clone().get_user_pass()?;
1263+
request.with_header("Authorization", format!("Basic {}", auth_token(user.as_ref().unwrap(), pass.as_ref().unwrap())))
1264+
}
1265+
Auth::None => request,
1266+
};
1267+
1268+
let response = request.send();
1269+
let response = response.map_err(|e| Error::Http(e))?;
1270+
1271+
let buffer = response.as_bytes();
1272+
let jsonrpc_response_maybe: Result<jsonrpc::Response> = serde_json::from_slice(&buffer).map_err(|e| Error::Json(e));
1273+
log_response(cmd, &jsonrpc_response_maybe);
1274+
let jsonrpc_response = jsonrpc_response_maybe?;
1275+
1276+
if jsonrpc_response.jsonrpc.is_some() && jsonrpc_response.jsonrpc != Some(From::from("2.0")) {
1277+
return Err(Error::JsonRpc(jsonrpc::error::Error::VersionMismatch));
1278+
}
1279+
if jsonrpc_response.id != id {
1280+
return Err(Error::JsonRpc(jsonrpc::error::Error::NonceMismatch));
12511281
}
12521282

1253-
let resp = self.client.send_request(req).map_err(Error::from);
1254-
log_response(cmd, &resp);
1255-
Ok(resp?.result()?)
1283+
jsonrpc_response.result().map_err(Error::JsonRpc)
12561284
}
12571285
}
12581286

client/src/error.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ use std::{error, fmt, io};
1313
use crate::bitcoin;
1414
use crate::bitcoin::hashes::hex;
1515
use crate::bitcoin::secp256k1;
16-
use jsonrpc;
1716
use serde_json;
1817

1918
/// The error type for errors produced in this library.
2019
#[derive(Debug)]
2120
pub enum Error {
2221
JsonRpc(jsonrpc::error::Error),
22+
Http(minreq::Error),
2323
Hex(hex::Error),
2424
Json(serde_json::error::Error),
2525
BitcoinSerialization(bitcoin::consensus::encode::Error),
@@ -79,6 +79,7 @@ impl fmt::Display for Error {
7979
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8080
match *self {
8181
Error::JsonRpc(ref e) => write!(f, "JSON-RPC error: {}", e),
82+
Error::Http(ref e) => write!(f, "HTTP error: {}", e),
8283
Error::Hex(ref e) => write!(f, "hex decode error: {}", e),
8384
Error::Json(ref e) => write!(f, "JSON error: {}", e),
8485
Error::BitcoinSerialization(ref e) => write!(f, "Bitcoin serialization error: {}", e),

0 commit comments

Comments
 (0)