bitcoincore_rpc/
client.rs

1// To the extent possible under law, the author(s) have dedicated all
2// copyright and related and neighboring rights to this software to
3// the public domain worldwide. This software is distributed without
4// any warranty.
5//
6// You should have received a copy of the CC0 Public Domain Dedication
7// along with this software.
8// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
9//
10
11use std::collections::HashMap;
12use std::fs::File;
13use std::io::{BufRead, BufReader};
14use std::iter::FromIterator;
15use std::path::PathBuf;
16use std::time::Duration;
17use std::{fmt, result};
18
19use crate::{bitcoin, deserialize_hex};
20use bitcoin::hex::DisplayHex;
21use jsonrpc;
22use jsonrpc::minreq_http::Builder;
23use serde;
24use serde_json;
25
26use crate::bitcoin::address::{NetworkChecked, NetworkUnchecked};
27use crate::bitcoin::hashes::hex::FromHex;
28use crate::bitcoin::secp256k1::ecdsa::Signature;
29use crate::bitcoin::{
30    Address, Amount, Block, OutPoint, PrivateKey, PublicKey, Script, Transaction,
31};
32use log::Level::{Debug, Trace, Warn};
33
34use crate::error::*;
35use crate::json;
36use crate::queryable;
37
38/// Crate-specific Result type, shorthand for `std::result::Result` with our
39/// crate-specific Error type;
40pub type Result<T> = result::Result<T, Error>;
41
42/// Outpoint that serializes and deserializes as a map, instead of a string,
43/// for use as RPC arguments
44#[derive(Clone, Debug, Serialize, Deserialize)]
45pub struct JsonOutPoint {
46    pub txid: bitcoin::Txid,
47    pub vout: u32,
48}
49
50impl From<OutPoint> for JsonOutPoint {
51    fn from(o: OutPoint) -> JsonOutPoint {
52        JsonOutPoint {
53            txid: o.txid,
54            vout: o.vout,
55        }
56    }
57}
58
59impl Into<OutPoint> for JsonOutPoint {
60    fn into(self) -> OutPoint {
61        OutPoint {
62            txid: self.txid,
63            vout: self.vout,
64        }
65    }
66}
67
68/// Shorthand for converting a variable into a serde_json::Value.
69fn into_json<T>(val: T) -> Result<serde_json::Value>
70where
71    T: serde::ser::Serialize,
72{
73    Ok(serde_json::to_value(val)?)
74}
75
76/// Shorthand for converting an Option into an Option<serde_json::Value>.
77fn opt_into_json<T>(opt: Option<T>) -> Result<serde_json::Value>
78where
79    T: serde::ser::Serialize,
80{
81    match opt {
82        Some(val) => Ok(into_json(val)?),
83        None => Ok(serde_json::Value::Null),
84    }
85}
86
87/// Shorthand for `serde_json::Value::Null`.
88fn null() -> serde_json::Value {
89    serde_json::Value::Null
90}
91
92/// Shorthand for an empty serde_json::Value array.
93fn empty_arr() -> serde_json::Value {
94    serde_json::Value::Array(vec![])
95}
96
97/// Shorthand for an empty serde_json object.
98fn empty_obj() -> serde_json::Value {
99    serde_json::Value::Object(Default::default())
100}
101
102/// Handle default values in the argument list
103///
104/// Substitute `Value::Null`s with corresponding values from `defaults` table,
105/// except when they are trailing, in which case just skip them altogether
106/// in returned list.
107///
108/// Note, that `defaults` corresponds to the last elements of `args`.
109///
110/// ```norust
111/// arg1 arg2 arg3 arg4
112///           def1 def2
113/// ```
114///
115/// Elements of `args` without corresponding `defaults` value, won't
116/// be substituted, because they are required.
117fn handle_defaults<'a, 'b>(
118    args: &'a mut [serde_json::Value],
119    defaults: &'b [serde_json::Value],
120) -> &'a [serde_json::Value] {
121    assert!(args.len() >= defaults.len());
122
123    // Pass over the optional arguments in backwards order, filling in defaults after the first
124    // non-null optional argument has been observed.
125    let mut first_non_null_optional_idx = None;
126    for i in 0..defaults.len() {
127        let args_i = args.len() - 1 - i;
128        let defaults_i = defaults.len() - 1 - i;
129        if args[args_i] == serde_json::Value::Null {
130            if first_non_null_optional_idx.is_some() {
131                if defaults[defaults_i] == serde_json::Value::Null {
132                    panic!("Missing `default` for argument idx {}", args_i);
133                }
134                args[args_i] = defaults[defaults_i].clone();
135            }
136        } else if first_non_null_optional_idx.is_none() {
137            first_non_null_optional_idx = Some(args_i);
138        }
139    }
140
141    let required_num = args.len() - defaults.len();
142
143    if let Some(i) = first_non_null_optional_idx {
144        &args[..i + 1]
145    } else {
146        &args[..required_num]
147    }
148}
149
150/// Convert a possible-null result into an Option.
151fn opt_result<T: for<'a> serde::de::Deserialize<'a>>(
152    result: serde_json::Value,
153) -> Result<Option<T>> {
154    if result == serde_json::Value::Null {
155        Ok(None)
156    } else {
157        Ok(serde_json::from_value(result)?)
158    }
159}
160
161/// Used to pass raw txs into the API.
162pub trait RawTx: Sized + Clone {
163    fn raw_hex(self) -> String;
164}
165
166impl<'a> RawTx for &'a Transaction {
167    fn raw_hex(self) -> String {
168        bitcoin::consensus::encode::serialize_hex(self)
169    }
170}
171
172impl<'a> RawTx for &'a [u8] {
173    fn raw_hex(self) -> String {
174        self.to_lower_hex_string()
175    }
176}
177
178impl<'a> RawTx for &'a Vec<u8> {
179    fn raw_hex(self) -> String {
180        self.to_lower_hex_string()
181    }
182}
183
184impl<'a> RawTx for &'a str {
185    fn raw_hex(self) -> String {
186        self.to_owned()
187    }
188}
189
190impl RawTx for String {
191    fn raw_hex(self) -> String {
192        self
193    }
194}
195
196/// The different authentication methods for the client.
197#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
198pub enum Auth {
199    None,
200    UserPass(String, String),
201    CookieFile(PathBuf),
202}
203
204impl Auth {
205    /// Convert into the arguments that jsonrpc::Client needs.
206    pub fn get_user_pass(self) -> Result<(Option<String>, Option<String>)> {
207        match self {
208            Auth::None => Ok((None, None)),
209            Auth::UserPass(u, p) => Ok((Some(u), Some(p))),
210            Auth::CookieFile(path) => {
211                let line = BufReader::new(File::open(path)?)
212                    .lines()
213                    .next()
214                    .ok_or(Error::InvalidCookieFile)??;
215                let colon = line.find(':').ok_or(Error::InvalidCookieFile)?;
216                Ok((Some(line[..colon].into()), Some(line[colon + 1..].into())))
217            }
218        }
219    }
220}
221
222pub trait RpcApi: Sized {
223    /// Call a `cmd` rpc with given `args` list
224    fn call<T: for<'a> serde::de::Deserialize<'a>>(
225        &self,
226        cmd: &str,
227        args: &[serde_json::Value],
228    ) -> Result<T>;
229
230    /// Query an object implementing `Querable` type
231    fn get_by_id<T: queryable::Queryable<Self>>(
232        &self,
233        id: &<T as queryable::Queryable<Self>>::Id,
234    ) -> Result<T> {
235        T::query(&self, &id)
236    }
237
238    fn get_network_info(&self) -> Result<json::GetNetworkInfoResult> {
239        self.call("getnetworkinfo", &[])
240    }
241
242    fn get_index_info(&self) -> Result<json::GetIndexInfoResult> {
243        self.call("getindexinfo", &[])
244    }
245
246    fn version(&self) -> Result<usize> {
247        #[derive(Deserialize)]
248        struct Response {
249            pub version: usize,
250        }
251        let res: Response = self.call("getnetworkinfo", &[])?;
252        Ok(res.version)
253    }
254
255    fn add_multisig_address(
256        &self,
257        nrequired: usize,
258        keys: &[json::PubKeyOrAddress],
259        label: Option<&str>,
260        address_type: Option<json::AddressType>,
261    ) -> Result<json::AddMultiSigAddressResult> {
262        let mut args = [
263            into_json(nrequired)?,
264            into_json(keys)?,
265            opt_into_json(label)?,
266            opt_into_json(address_type)?,
267        ];
268        self.call("addmultisigaddress", handle_defaults(&mut args, &[into_json("")?, null()]))
269    }
270
271    fn load_wallet(&self, wallet: &str) -> Result<json::LoadWalletResult> {
272        self.call("loadwallet", &[wallet.into()])
273    }
274
275    fn unload_wallet(&self, wallet: Option<&str>) -> Result<Option<json::UnloadWalletResult>> {
276        let mut args = [opt_into_json(wallet)?];
277        self.call("unloadwallet", handle_defaults(&mut args, &[null()]))
278    }
279
280    fn create_wallet(
281        &self,
282        wallet: &str,
283        disable_private_keys: Option<bool>,
284        blank: Option<bool>,
285        passphrase: Option<&str>,
286        avoid_reuse: Option<bool>,
287    ) -> Result<json::LoadWalletResult> {
288        let mut args = [
289            wallet.into(),
290            opt_into_json(disable_private_keys)?,
291            opt_into_json(blank)?,
292            opt_into_json(passphrase)?,
293            opt_into_json(avoid_reuse)?,
294        ];
295        self.call(
296            "createwallet",
297            handle_defaults(&mut args, &[false.into(), false.into(), into_json("")?, false.into()]),
298        )
299    }
300
301    fn list_wallets(&self) -> Result<Vec<String>> {
302        self.call("listwallets", &[])
303    }
304
305    fn list_wallet_dir(&self) -> Result<Vec<String>> {
306        let result: json::ListWalletDirResult = self.call("listwalletdir", &[])?;
307        let names = result.wallets.into_iter().map(|x| x.name).collect();
308        Ok(names)
309    }
310
311    fn get_wallet_info(&self) -> Result<json::GetWalletInfoResult> {
312        self.call("getwalletinfo", &[])
313    }
314
315    fn backup_wallet(&self, destination: Option<&str>) -> Result<()> {
316        let mut args = [opt_into_json(destination)?];
317        self.call("backupwallet", handle_defaults(&mut args, &[null()]))
318    }
319
320    fn dump_private_key(&self, address: &Address) -> Result<PrivateKey> {
321        self.call("dumpprivkey", &[address.to_string().into()])
322    }
323
324    fn encrypt_wallet(&self, passphrase: &str) -> Result<()> {
325        self.call("encryptwallet", &[into_json(passphrase)?])
326    }
327
328    fn get_difficulty(&self) -> Result<f64> {
329        self.call("getdifficulty", &[])
330    }
331
332    fn get_connection_count(&self) -> Result<usize> {
333        self.call("getconnectioncount", &[])
334    }
335
336    fn get_block(&self, hash: &bitcoin::BlockHash) -> Result<Block> {
337        let hex: String = self.call("getblock", &[into_json(hash)?, 0.into()])?;
338        deserialize_hex(&hex)
339    }
340
341    fn get_block_hex(&self, hash: &bitcoin::BlockHash) -> Result<String> {
342        self.call("getblock", &[into_json(hash)?, 0.into()])
343    }
344
345    fn get_block_info(&self, hash: &bitcoin::BlockHash) -> Result<json::GetBlockResult> {
346        self.call("getblock", &[into_json(hash)?, 1.into()])
347    }
348    //TODO(stevenroose) add getblock_txs
349
350    fn get_block_header(&self, hash: &bitcoin::BlockHash) -> Result<bitcoin::block::Header> {
351        let hex: String = self.call("getblockheader", &[into_json(hash)?, false.into()])?;
352        deserialize_hex(&hex)
353    }
354
355    fn get_block_header_info(
356        &self,
357        hash: &bitcoin::BlockHash,
358    ) -> Result<json::GetBlockHeaderResult> {
359        self.call("getblockheader", &[into_json(hash)?, true.into()])
360    }
361
362    fn get_mining_info(&self) -> Result<json::GetMiningInfoResult> {
363        self.call("getmininginfo", &[])
364    }
365
366    fn get_block_template(
367        &self,
368        mode: json::GetBlockTemplateModes,
369        rules: &[json::GetBlockTemplateRules],
370        capabilities: &[json::GetBlockTemplateCapabilities],
371    ) -> Result<json::GetBlockTemplateResult> {
372        #[derive(Serialize)]
373        struct Argument<'a> {
374            mode: json::GetBlockTemplateModes,
375            rules: &'a [json::GetBlockTemplateRules],
376            capabilities: &'a [json::GetBlockTemplateCapabilities],
377        }
378
379        self.call(
380            "getblocktemplate",
381            &[into_json(Argument {
382                mode: mode,
383                rules: rules,
384                capabilities: capabilities,
385            })?],
386        )
387    }
388
389    /// Returns a data structure containing various state info regarding
390    /// blockchain processing.
391    fn get_blockchain_info(&self) -> Result<json::GetBlockchainInfoResult> {
392        let mut raw: serde_json::Value = self.call("getblockchaininfo", &[])?;
393        // The softfork fields are not backwards compatible:
394        // - 0.18.x returns a "softforks" array and a "bip9_softforks" map.
395        // - 0.19.x returns a "softforks" map.
396        Ok(if self.version()? < 190000 {
397            use crate::Error::UnexpectedStructure as err;
398
399            // First, remove both incompatible softfork fields.
400            // We need to scope the mutable ref here for v1.29 borrowck.
401            let (bip9_softforks, old_softforks) = {
402                let map = raw.as_object_mut().ok_or(err)?;
403                let bip9_softforks = map.remove("bip9_softforks").ok_or(err)?;
404                let old_softforks = map.remove("softforks").ok_or(err)?;
405                // Put back an empty "softforks" field.
406                map.insert("softforks".into(), serde_json::Map::new().into());
407                (bip9_softforks, old_softforks)
408            };
409            let mut ret: json::GetBlockchainInfoResult = serde_json::from_value(raw)?;
410
411            // Then convert both softfork types and add them.
412            for sf in old_softforks.as_array().ok_or(err)?.iter() {
413                let json = sf.as_object().ok_or(err)?;
414                let id = json.get("id").ok_or(err)?.as_str().ok_or(err)?;
415                let reject = json.get("reject").ok_or(err)?.as_object().ok_or(err)?;
416                let active = reject.get("status").ok_or(err)?.as_bool().ok_or(err)?;
417                ret.softforks.insert(
418                    id.into(),
419                    json::Softfork {
420                        type_: json::SoftforkType::Buried,
421                        bip9: None,
422                        height: None,
423                        active: active,
424                    },
425                );
426            }
427            for (id, sf) in bip9_softforks.as_object().ok_or(err)?.iter() {
428                #[derive(Deserialize)]
429                struct OldBip9SoftFork {
430                    pub status: json::Bip9SoftforkStatus,
431                    pub bit: Option<u8>,
432                    #[serde(rename = "startTime")]
433                    pub start_time: i64,
434                    pub timeout: u64,
435                    pub since: u32,
436                    pub statistics: Option<json::Bip9SoftforkStatistics>,
437                }
438                let sf: OldBip9SoftFork = serde_json::from_value(sf.clone())?;
439                ret.softforks.insert(
440                    id.clone(),
441                    json::Softfork {
442                        type_: json::SoftforkType::Bip9,
443                        bip9: Some(json::Bip9SoftforkInfo {
444                            status: sf.status,
445                            bit: sf.bit,
446                            start_time: sf.start_time,
447                            timeout: sf.timeout,
448                            since: sf.since,
449                            statistics: sf.statistics,
450                        }),
451                        height: None,
452                        active: sf.status == json::Bip9SoftforkStatus::Active,
453                    },
454                );
455            }
456            ret
457        } else {
458            serde_json::from_value(raw)?
459        })
460    }
461
462    /// Returns the numbers of block in the longest chain.
463    fn get_block_count(&self) -> Result<u64> {
464        self.call("getblockcount", &[])
465    }
466
467    /// Returns the hash of the best (tip) block in the longest blockchain.
468    fn get_best_block_hash(&self) -> Result<bitcoin::BlockHash> {
469        self.call("getbestblockhash", &[])
470    }
471
472    /// Get block hash at a given height
473    fn get_block_hash(&self, height: u64) -> Result<bitcoin::BlockHash> {
474        self.call("getblockhash", &[height.into()])
475    }
476
477    fn get_block_stats(&self, height: u64) -> Result<json::GetBlockStatsResult> {
478        self.call("getblockstats", &[height.into()])
479    }
480
481    fn get_block_stats_fields(
482        &self,
483        height: u64,
484        fields: &[json::BlockStatsFields],
485    ) -> Result<json::GetBlockStatsResultPartial> {
486        self.call("getblockstats", &[height.into(), fields.into()])
487    }
488
489    fn get_raw_transaction(
490        &self,
491        txid: &bitcoin::Txid,
492        block_hash: Option<&bitcoin::BlockHash>,
493    ) -> Result<Transaction> {
494        let mut args = [into_json(txid)?, into_json(false)?, opt_into_json(block_hash)?];
495        let hex: String = self.call("getrawtransaction", handle_defaults(&mut args, &[null()]))?;
496        deserialize_hex(&hex)
497    }
498
499    fn get_raw_transaction_hex(
500        &self,
501        txid: &bitcoin::Txid,
502        block_hash: Option<&bitcoin::BlockHash>,
503    ) -> Result<String> {
504        let mut args = [into_json(txid)?, into_json(false)?, opt_into_json(block_hash)?];
505        self.call("getrawtransaction", handle_defaults(&mut args, &[null()]))
506    }
507
508    fn get_raw_transaction_info(
509        &self,
510        txid: &bitcoin::Txid,
511        block_hash: Option<&bitcoin::BlockHash>,
512    ) -> Result<json::GetRawTransactionResult> {
513        let mut args = [into_json(txid)?, into_json(true)?, opt_into_json(block_hash)?];
514        self.call("getrawtransaction", handle_defaults(&mut args, &[null()]))
515    }
516
517    fn get_block_filter(
518        &self,
519        block_hash: &bitcoin::BlockHash,
520    ) -> Result<json::GetBlockFilterResult> {
521        self.call("getblockfilter", &[into_json(block_hash)?])
522    }
523
524    fn get_balance(
525        &self,
526        minconf: Option<usize>,
527        include_watchonly: Option<bool>,
528    ) -> Result<Amount> {
529        let mut args = ["*".into(), opt_into_json(minconf)?, opt_into_json(include_watchonly)?];
530        Ok(Amount::from_btc(
531            self.call("getbalance", handle_defaults(&mut args, &[0.into(), null()]))?,
532        )?)
533    }
534
535    fn get_balances(&self) -> Result<json::GetBalancesResult> {
536        Ok(self.call("getbalances", &[])?)
537    }
538
539    fn get_received_by_address(&self, address: &Address, minconf: Option<u32>) -> Result<Amount> {
540        let mut args = [address.to_string().into(), opt_into_json(minconf)?];
541        Ok(Amount::from_btc(
542            self.call("getreceivedbyaddress", handle_defaults(&mut args, &[null()]))?,
543        )?)
544    }
545
546    fn get_transaction(
547        &self,
548        txid: &bitcoin::Txid,
549        include_watchonly: Option<bool>,
550    ) -> Result<json::GetTransactionResult> {
551        let mut args = [into_json(txid)?, opt_into_json(include_watchonly)?];
552        self.call("gettransaction", handle_defaults(&mut args, &[null()]))
553    }
554
555    fn list_transactions(
556        &self,
557        label: Option<&str>,
558        count: Option<usize>,
559        skip: Option<usize>,
560        include_watchonly: Option<bool>,
561    ) -> Result<Vec<json::ListTransactionResult>> {
562        let mut args = [
563            label.unwrap_or("*").into(),
564            opt_into_json(count)?,
565            opt_into_json(skip)?,
566            opt_into_json(include_watchonly)?,
567        ];
568        self.call("listtransactions", handle_defaults(&mut args, &[10.into(), 0.into(), null()]))
569    }
570
571    fn list_since_block(
572        &self,
573        blockhash: Option<&bitcoin::BlockHash>,
574        target_confirmations: Option<usize>,
575        include_watchonly: Option<bool>,
576        include_removed: Option<bool>,
577    ) -> Result<json::ListSinceBlockResult> {
578        let mut args = [
579            opt_into_json(blockhash)?,
580            opt_into_json(target_confirmations)?,
581            opt_into_json(include_watchonly)?,
582            opt_into_json(include_removed)?,
583        ];
584        self.call("listsinceblock", handle_defaults(&mut args, &[null()]))
585    }
586
587    fn get_tx_out(
588        &self,
589        txid: &bitcoin::Txid,
590        vout: u32,
591        include_mempool: Option<bool>,
592    ) -> Result<Option<json::GetTxOutResult>> {
593        let mut args = [into_json(txid)?, into_json(vout)?, opt_into_json(include_mempool)?];
594        opt_result(self.call("gettxout", handle_defaults(&mut args, &[null()]))?)
595    }
596
597    fn get_tx_out_proof(
598        &self,
599        txids: &[bitcoin::Txid],
600        block_hash: Option<&bitcoin::BlockHash>,
601    ) -> Result<Vec<u8>> {
602        let mut args = [into_json(txids)?, opt_into_json(block_hash)?];
603        let hex: String = self.call("gettxoutproof", handle_defaults(&mut args, &[null()]))?;
604        Ok(FromHex::from_hex(&hex)?)
605    }
606
607    fn import_public_key(
608        &self,
609        pubkey: &PublicKey,
610        label: Option<&str>,
611        rescan: Option<bool>,
612    ) -> Result<()> {
613        let mut args = [pubkey.to_string().into(), opt_into_json(label)?, opt_into_json(rescan)?];
614        self.call("importpubkey", handle_defaults(&mut args, &[into_json("")?, null()]))
615    }
616
617    fn import_private_key(
618        &self,
619        privkey: &PrivateKey,
620        label: Option<&str>,
621        rescan: Option<bool>,
622    ) -> Result<()> {
623        let mut args = [privkey.to_string().into(), opt_into_json(label)?, opt_into_json(rescan)?];
624        self.call("importprivkey", handle_defaults(&mut args, &[into_json("")?, null()]))
625    }
626
627    fn import_address(
628        &self,
629        address: &Address,
630        label: Option<&str>,
631        rescan: Option<bool>,
632    ) -> Result<()> {
633        let mut args = [address.to_string().into(), opt_into_json(label)?, opt_into_json(rescan)?];
634        self.call("importaddress", handle_defaults(&mut args, &[into_json("")?, null()]))
635    }
636
637    fn import_address_script(
638        &self,
639        script: &Script,
640        label: Option<&str>,
641        rescan: Option<bool>,
642        p2sh: Option<bool>,
643    ) -> Result<()> {
644        let mut args = [
645            script.to_hex_string().into(),
646            opt_into_json(label)?,
647            opt_into_json(rescan)?,
648            opt_into_json(p2sh)?,
649        ];
650        self.call(
651            "importaddress",
652            handle_defaults(&mut args, &[into_json("")?, true.into(), null()]),
653        )
654    }
655
656    fn import_multi(
657        &self,
658        requests: &[json::ImportMultiRequest],
659        options: Option<&json::ImportMultiOptions>,
660    ) -> Result<Vec<json::ImportMultiResult>> {
661        let mut json_requests = Vec::with_capacity(requests.len());
662        for req in requests {
663            json_requests.push(serde_json::to_value(req)?);
664        }
665        let mut args = [json_requests.into(), opt_into_json(options)?];
666        self.call("importmulti", handle_defaults(&mut args, &[null()]))
667    }
668
669    fn import_descriptors(
670        &self,
671        req: Vec<json::ImportDescriptors>,
672    ) -> Result<Vec<json::ImportMultiResult>> {
673        let json_request = serde_json::to_value(req)?;
674        self.call("importdescriptors", handle_defaults(&mut [json_request.into()], &[null()]))
675    }
676
677    fn list_descriptors(&self, private: Option<bool>) -> Result<json::ListDescriptorsResult> {
678        let mut args = [opt_into_json(private)?];
679        self.call("listdescriptors", handle_defaults(&mut args, &[null()]))
680    }
681
682    fn set_label(&self, address: &Address, label: &str) -> Result<()> {
683        self.call("setlabel", &[address.to_string().into(), label.into()])
684    }
685
686    fn key_pool_refill(&self, new_size: Option<usize>) -> Result<()> {
687        let mut args = [opt_into_json(new_size)?];
688        self.call("keypoolrefill", handle_defaults(&mut args, &[null()]))
689    }
690
691    fn list_unspent(
692        &self,
693        minconf: Option<usize>,
694        maxconf: Option<usize>,
695        addresses: Option<&[&Address<NetworkChecked>]>,
696        include_unsafe: Option<bool>,
697        query_options: Option<json::ListUnspentQueryOptions>,
698    ) -> Result<Vec<json::ListUnspentResultEntry>> {
699        let mut args = [
700            opt_into_json(minconf)?,
701            opt_into_json(maxconf)?,
702            opt_into_json(addresses)?,
703            opt_into_json(include_unsafe)?,
704            opt_into_json(query_options)?,
705        ];
706        let defaults = [into_json(0)?, into_json(9999999)?, empty_arr(), into_json(true)?, null()];
707        self.call("listunspent", handle_defaults(&mut args, &defaults))
708    }
709
710    /// To unlock, use [unlock_unspent].
711    fn lock_unspent(&self, outputs: &[OutPoint]) -> Result<bool> {
712        let outputs: Vec<_> = outputs
713            .into_iter()
714            .map(|o| serde_json::to_value(JsonOutPoint::from(*o)).unwrap())
715            .collect();
716        self.call("lockunspent", &[false.into(), outputs.into()])
717    }
718
719    fn unlock_unspent(&self, outputs: &[OutPoint]) -> Result<bool> {
720        let outputs: Vec<_> = outputs
721            .into_iter()
722            .map(|o| serde_json::to_value(JsonOutPoint::from(*o)).unwrap())
723            .collect();
724        self.call("lockunspent", &[true.into(), outputs.into()])
725    }
726
727    /// Unlock all unspent UTXOs.
728    fn unlock_unspent_all(&self) -> Result<bool> {
729        self.call("lockunspent", &[true.into()])
730    }
731
732    fn list_received_by_address(
733        &self,
734        address_filter: Option<&Address>,
735        minconf: Option<u32>,
736        include_empty: Option<bool>,
737        include_watchonly: Option<bool>,
738    ) -> Result<Vec<json::ListReceivedByAddressResult>> {
739        let mut args = [
740            opt_into_json(minconf)?,
741            opt_into_json(include_empty)?,
742            opt_into_json(include_watchonly)?,
743            opt_into_json(address_filter)?,
744        ];
745        let defaults = [1.into(), false.into(), false.into(), null()];
746        self.call("listreceivedbyaddress", handle_defaults(&mut args, &defaults))
747    }
748
749    fn create_psbt(
750        &self,
751        inputs: &[json::CreateRawTransactionInput],
752        outputs: &HashMap<String, Amount>,
753        locktime: Option<i64>,
754        replaceable: Option<bool>,
755    ) -> Result<String> {
756        let outs_converted = serde_json::Map::from_iter(
757            outputs.iter().map(|(k, v)| (k.clone(), serde_json::Value::from(v.to_btc()))),
758        );
759        self.call(
760            "createpsbt",
761            &[
762                into_json(inputs)?,
763                into_json(outs_converted)?,
764                into_json(locktime)?,
765                into_json(replaceable)?,
766            ],
767        )
768    }
769
770    fn create_raw_transaction_hex(
771        &self,
772        utxos: &[json::CreateRawTransactionInput],
773        outs: &HashMap<String, Amount>,
774        locktime: Option<i64>,
775        replaceable: Option<bool>,
776    ) -> Result<String> {
777        let outs_converted = serde_json::Map::from_iter(
778            outs.iter().map(|(k, v)| (k.clone(), serde_json::Value::from(v.to_btc()))),
779        );
780        let mut args = [
781            into_json(utxos)?,
782            into_json(outs_converted)?,
783            opt_into_json(locktime)?,
784            opt_into_json(replaceable)?,
785        ];
786        let defaults = [into_json(0i64)?, null()];
787        self.call("createrawtransaction", handle_defaults(&mut args, &defaults))
788    }
789
790    fn create_raw_transaction(
791        &self,
792        utxos: &[json::CreateRawTransactionInput],
793        outs: &HashMap<String, Amount>,
794        locktime: Option<i64>,
795        replaceable: Option<bool>,
796    ) -> Result<Transaction> {
797        let hex: String = self.create_raw_transaction_hex(utxos, outs, locktime, replaceable)?;
798        deserialize_hex(&hex)
799    }
800
801    fn decode_raw_transaction<R: RawTx>(
802        &self,
803        tx: R,
804        is_witness: Option<bool>,
805    ) -> Result<json::DecodeRawTransactionResult> {
806        let mut args = [tx.raw_hex().into(), opt_into_json(is_witness)?];
807        let defaults = [null()];
808        self.call("decoderawtransaction", handle_defaults(&mut args, &defaults))
809    }
810
811    fn fund_raw_transaction<R: RawTx>(
812        &self,
813        tx: R,
814        options: Option<&json::FundRawTransactionOptions>,
815        is_witness: Option<bool>,
816    ) -> Result<json::FundRawTransactionResult> {
817        let mut args = [tx.raw_hex().into(), opt_into_json(options)?, opt_into_json(is_witness)?];
818        let defaults = [empty_obj(), null()];
819        self.call("fundrawtransaction", handle_defaults(&mut args, &defaults))
820    }
821
822    #[deprecated]
823    fn sign_raw_transaction<R: RawTx>(
824        &self,
825        tx: R,
826        utxos: Option<&[json::SignRawTransactionInput]>,
827        private_keys: Option<&[PrivateKey]>,
828        sighash_type: Option<json::SigHashType>,
829    ) -> Result<json::SignRawTransactionResult> {
830        let mut args = [
831            tx.raw_hex().into(),
832            opt_into_json(utxos)?,
833            opt_into_json(private_keys)?,
834            opt_into_json(sighash_type)?,
835        ];
836        let defaults = [empty_arr(), empty_arr(), null()];
837        self.call("signrawtransaction", handle_defaults(&mut args, &defaults))
838    }
839
840    fn sign_raw_transaction_with_wallet<R: RawTx>(
841        &self,
842        tx: R,
843        utxos: Option<&[json::SignRawTransactionInput]>,
844        sighash_type: Option<json::SigHashType>,
845    ) -> Result<json::SignRawTransactionResult> {
846        let mut args = [tx.raw_hex().into(), opt_into_json(utxos)?, opt_into_json(sighash_type)?];
847        let defaults = [empty_arr(), null()];
848        self.call("signrawtransactionwithwallet", handle_defaults(&mut args, &defaults))
849    }
850
851    fn sign_raw_transaction_with_key<R: RawTx>(
852        &self,
853        tx: R,
854        privkeys: &[PrivateKey],
855        prevtxs: Option<&[json::SignRawTransactionInput]>,
856        sighash_type: Option<json::SigHashType>,
857    ) -> Result<json::SignRawTransactionResult> {
858        let mut args = [
859            tx.raw_hex().into(),
860            into_json(privkeys)?,
861            opt_into_json(prevtxs)?,
862            opt_into_json(sighash_type)?,
863        ];
864        let defaults = [empty_arr(), null()];
865        self.call("signrawtransactionwithkey", handle_defaults(&mut args, &defaults))
866    }
867
868    fn test_mempool_accept<R: RawTx>(
869        &self,
870        rawtxs: &[R],
871    ) -> Result<Vec<json::TestMempoolAcceptResult>> {
872        let hexes: Vec<serde_json::Value> =
873            rawtxs.to_vec().into_iter().map(|r| r.raw_hex().into()).collect();
874        self.call("testmempoolaccept", &[hexes.into()])
875    }
876
877    fn stop(&self) -> Result<String> {
878        self.call("stop", &[])
879    }
880
881    fn verify_message(
882        &self,
883        address: &Address,
884        signature: &Signature,
885        message: &str,
886    ) -> Result<bool> {
887        let args = [address.to_string().into(), signature.to_string().into(), into_json(message)?];
888        self.call("verifymessage", &args)
889    }
890
891    /// Generate new address under own control
892    fn get_new_address(
893        &self,
894        label: Option<&str>,
895        address_type: Option<json::AddressType>,
896    ) -> Result<Address<NetworkUnchecked>> {
897        self.call("getnewaddress", &[opt_into_json(label)?, opt_into_json(address_type)?])
898    }
899
900    /// Generate new address for receiving change
901    fn get_raw_change_address(
902        &self,
903        address_type: Option<json::AddressType>,
904    ) -> Result<Address<NetworkUnchecked>> {
905        self.call("getrawchangeaddress", &[opt_into_json(address_type)?])
906    }
907
908    fn get_address_info(&self, address: &Address) -> Result<json::GetAddressInfoResult> {
909        self.call("getaddressinfo", &[address.to_string().into()])
910    }
911
912    /// Mine `block_num` blocks and pay coinbase to `address`
913    ///
914    /// Returns hashes of the generated blocks
915    fn generate_to_address(
916        &self,
917        block_num: u64,
918        address: &Address<NetworkChecked>,
919    ) -> Result<Vec<bitcoin::BlockHash>> {
920        self.call("generatetoaddress", &[block_num.into(), address.to_string().into()])
921    }
922
923    /// Mine up to block_num blocks immediately (before the RPC call returns)
924    /// to an address in the wallet.
925    fn generate(&self, block_num: u64, maxtries: Option<u64>) -> Result<Vec<bitcoin::BlockHash>> {
926        self.call("generate", &[block_num.into(), opt_into_json(maxtries)?])
927    }
928
929    /// Mark a block as invalid by `block_hash`
930    fn invalidate_block(&self, block_hash: &bitcoin::BlockHash) -> Result<()> {
931        self.call("invalidateblock", &[into_json(block_hash)?])
932    }
933
934    /// Mark a block as valid by `block_hash`
935    fn reconsider_block(&self, block_hash: &bitcoin::BlockHash) -> Result<()> {
936        self.call("reconsiderblock", &[into_json(block_hash)?])
937    }
938
939    /// Returns details on the active state of the TX memory pool
940    fn get_mempool_info(&self) -> Result<json::GetMempoolInfoResult> {
941        self.call("getmempoolinfo", &[])
942    }
943
944    /// Get txids of all transactions in a memory pool
945    fn get_raw_mempool(&self) -> Result<Vec<bitcoin::Txid>> {
946        self.call("getrawmempool", &[])
947    }
948
949    /// Get details for the transactions in a memory pool
950    fn get_raw_mempool_verbose(
951        &self,
952    ) -> Result<HashMap<bitcoin::Txid, json::GetMempoolEntryResult>> {
953        self.call("getrawmempool", &[into_json(true)?])
954    }
955
956    /// Get mempool data for given transaction
957    fn get_mempool_entry(&self, txid: &bitcoin::Txid) -> Result<json::GetMempoolEntryResult> {
958        self.call("getmempoolentry", &[into_json(txid)?])
959    }
960
961    /// Get information about all known tips in the block tree, including the
962    /// main chain as well as stale branches.
963    fn get_chain_tips(&self) -> Result<json::GetChainTipsResult> {
964        self.call("getchaintips", &[])
965    }
966
967    fn send_to_address(
968        &self,
969        address: &Address<NetworkChecked>,
970        amount: Amount,
971        comment: Option<&str>,
972        comment_to: Option<&str>,
973        subtract_fee: Option<bool>,
974        replaceable: Option<bool>,
975        confirmation_target: Option<u32>,
976        estimate_mode: Option<json::EstimateMode>,
977    ) -> Result<bitcoin::Txid> {
978        let mut args = [
979            address.to_string().into(),
980            into_json(amount.to_btc())?,
981            opt_into_json(comment)?,
982            opt_into_json(comment_to)?,
983            opt_into_json(subtract_fee)?,
984            opt_into_json(replaceable)?,
985            opt_into_json(confirmation_target)?,
986            opt_into_json(estimate_mode)?,
987        ];
988        self.call(
989            "sendtoaddress",
990            handle_defaults(
991                &mut args,
992                &["".into(), "".into(), false.into(), false.into(), 6.into(), null()],
993            ),
994        )
995    }
996
997    /// Attempts to add a node to the addnode list.
998    /// Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).
999    fn add_node(&self, addr: &str) -> Result<()> {
1000        self.call("addnode", &[into_json(&addr)?, into_json("add")?])
1001    }
1002
1003    /// Attempts to remove a node from the addnode list.
1004    fn remove_node(&self, addr: &str) -> Result<()> {
1005        self.call("addnode", &[into_json(&addr)?, into_json("remove")?])
1006    }
1007
1008    /// Attempts to connect to a node without permanently adding it to the addnode list.
1009    fn onetry_node(&self, addr: &str) -> Result<()> {
1010        self.call("addnode", &[into_json(&addr)?, into_json("onetry")?])
1011    }
1012
1013    /// Immediately disconnects from the specified peer node.
1014    fn disconnect_node(&self, addr: &str) -> Result<()> {
1015        self.call("disconnectnode", &[into_json(&addr)?])
1016    }
1017
1018    fn disconnect_node_by_id(&self, node_id: u32) -> Result<()> {
1019        self.call("disconnectnode", &[into_json("")?, into_json(node_id)?])
1020    }
1021
1022    /// Returns information about the given added node, or all added nodes (note that onetry addnodes are not listed here)
1023    fn get_added_node_info(&self, node: Option<&str>) -> Result<Vec<json::GetAddedNodeInfoResult>> {
1024        if let Some(addr) = node {
1025            self.call("getaddednodeinfo", &[into_json(&addr)?])
1026        } else {
1027            self.call("getaddednodeinfo", &[])
1028        }
1029    }
1030
1031    /// Return known addresses which can potentially be used to find new nodes in the network
1032    fn get_node_addresses(
1033        &self,
1034        count: Option<usize>,
1035    ) -> Result<Vec<json::GetNodeAddressesResult>> {
1036        let cnt = count.unwrap_or(1);
1037        self.call("getnodeaddresses", &[into_json(&cnt)?])
1038    }
1039
1040    /// List all banned IPs/Subnets.
1041    fn list_banned(&self) -> Result<Vec<json::ListBannedResult>> {
1042        self.call("listbanned", &[])
1043    }
1044
1045    /// Clear all banned IPs.
1046    fn clear_banned(&self) -> Result<()> {
1047        self.call("clearbanned", &[])
1048    }
1049
1050    /// Attempts to add an IP/Subnet to the banned list.
1051    fn add_ban(&self, subnet: &str, bantime: u64, absolute: bool) -> Result<()> {
1052        self.call(
1053            "setban",
1054            &[into_json(&subnet)?, into_json("add")?, into_json(&bantime)?, into_json(&absolute)?],
1055        )
1056    }
1057
1058    /// Attempts to remove an IP/Subnet from the banned list.
1059    fn remove_ban(&self, subnet: &str) -> Result<()> {
1060        self.call("setban", &[into_json(&subnet)?, into_json("remove")?])
1061    }
1062
1063    /// Disable/enable all p2p network activity.
1064    fn set_network_active(&self, state: bool) -> Result<bool> {
1065        self.call("setnetworkactive", &[into_json(&state)?])
1066    }
1067
1068    /// Returns data about each connected network node as an array of
1069    /// [`PeerInfo`][]
1070    ///
1071    /// [`PeerInfo`]: net/struct.PeerInfo.html
1072    fn get_peer_info(&self) -> Result<Vec<json::GetPeerInfoResult>> {
1073        self.call("getpeerinfo", &[])
1074    }
1075
1076    /// Requests that a ping be sent to all other nodes, to measure ping
1077    /// time.
1078    ///
1079    /// Results provided in `getpeerinfo`, `pingtime` and `pingwait` fields
1080    /// are decimal seconds.
1081    ///
1082    /// Ping command is handled in queue with all other commands, so it
1083    /// measures processing backlog, not just network ping.
1084    fn ping(&self) -> Result<()> {
1085        self.call("ping", &[])
1086    }
1087
1088    fn send_raw_transaction<R: RawTx>(&self, tx: R) -> Result<bitcoin::Txid> {
1089        self.call("sendrawtransaction", &[tx.raw_hex().into()])
1090    }
1091
1092    fn estimate_smart_fee(
1093        &self,
1094        conf_target: u16,
1095        estimate_mode: Option<json::EstimateMode>,
1096    ) -> Result<json::EstimateSmartFeeResult> {
1097        let mut args = [into_json(conf_target)?, opt_into_json(estimate_mode)?];
1098        self.call("estimatesmartfee", handle_defaults(&mut args, &[null()]))
1099    }
1100
1101    /// Waits for a specific new block and returns useful info about it.
1102    /// Returns the current block on timeout or exit.
1103    ///
1104    /// # Arguments
1105    ///
1106    /// 1. `timeout`: Time in milliseconds to wait for a response. 0
1107    /// indicates no timeout.
1108    fn wait_for_new_block(&self, timeout: u64) -> Result<json::BlockRef> {
1109        self.call("waitfornewblock", &[into_json(timeout)?])
1110    }
1111
1112    /// Waits for a specific new block and returns useful info about it.
1113    /// Returns the current block on timeout or exit.
1114    ///
1115    /// # Arguments
1116    ///
1117    /// 1. `blockhash`: Block hash to wait for.
1118    /// 2. `timeout`: Time in milliseconds to wait for a response. 0
1119    /// indicates no timeout.
1120    fn wait_for_block(
1121        &self,
1122        blockhash: &bitcoin::BlockHash,
1123        timeout: u64,
1124    ) -> Result<json::BlockRef> {
1125        let args = [into_json(blockhash)?, into_json(timeout)?];
1126        self.call("waitforblock", &args)
1127    }
1128
1129    fn wallet_create_funded_psbt(
1130        &self,
1131        inputs: &[json::CreateRawTransactionInput],
1132        outputs: &HashMap<String, Amount>,
1133        locktime: Option<i64>,
1134        options: Option<json::WalletCreateFundedPsbtOptions>,
1135        bip32derivs: Option<bool>,
1136    ) -> Result<json::WalletCreateFundedPsbtResult> {
1137        let outputs_converted = serde_json::Map::from_iter(
1138            outputs.iter().map(|(k, v)| (k.clone(), serde_json::Value::from(v.to_btc()))),
1139        );
1140        let mut args = [
1141            into_json(inputs)?,
1142            into_json(outputs_converted)?,
1143            opt_into_json(locktime)?,
1144            opt_into_json(options)?,
1145            opt_into_json(bip32derivs)?,
1146        ];
1147        self.call(
1148            "walletcreatefundedpsbt",
1149            handle_defaults(&mut args, &[0.into(), serde_json::Map::new().into(), false.into()]),
1150        )
1151    }
1152
1153    fn wallet_process_psbt(
1154        &self,
1155        psbt: &str,
1156        sign: Option<bool>,
1157        sighash_type: Option<json::SigHashType>,
1158        bip32derivs: Option<bool>,
1159    ) -> Result<json::WalletProcessPsbtResult> {
1160        let mut args = [
1161            into_json(psbt)?,
1162            opt_into_json(sign)?,
1163            opt_into_json(sighash_type)?,
1164            opt_into_json(bip32derivs)?,
1165        ];
1166        let defaults = [
1167            true.into(),
1168            into_json(json::SigHashType::from(bitcoin::sighash::EcdsaSighashType::All))?,
1169            true.into(),
1170        ];
1171        self.call("walletprocesspsbt", handle_defaults(&mut args, &defaults))
1172    }
1173
1174    fn get_descriptor_info(&self, desc: &str) -> Result<json::GetDescriptorInfoResult> {
1175        self.call("getdescriptorinfo", &[desc.to_string().into()])
1176    }
1177
1178    fn join_psbt(&self, psbts: &[String]) -> Result<String> {
1179        self.call("joinpsbts", &[into_json(psbts)?])
1180    }
1181
1182    fn combine_psbt(&self, psbts: &[String]) -> Result<String> {
1183        self.call("combinepsbt", &[into_json(psbts)?])
1184    }
1185
1186    fn combine_raw_transaction(&self, hex_strings: &[String]) -> Result<String> {
1187        self.call("combinerawtransaction", &[into_json(hex_strings)?])
1188    }
1189
1190    fn finalize_psbt(&self, psbt: &str, extract: Option<bool>) -> Result<json::FinalizePsbtResult> {
1191        let mut args = [into_json(psbt)?, opt_into_json(extract)?];
1192        self.call("finalizepsbt", handle_defaults(&mut args, &[true.into()]))
1193    }
1194
1195    fn derive_addresses(
1196        &self,
1197        descriptor: &str,
1198        range: Option<[u32; 2]>,
1199    ) -> Result<Vec<Address<NetworkUnchecked>>> {
1200        let mut args = [into_json(descriptor)?, opt_into_json(range)?];
1201        self.call("deriveaddresses", handle_defaults(&mut args, &[null()]))
1202    }
1203
1204    fn rescan_blockchain(
1205        &self,
1206        start_from: Option<usize>,
1207        stop_height: Option<usize>,
1208    ) -> Result<(usize, Option<usize>)> {
1209        let mut args = [opt_into_json(start_from)?, opt_into_json(stop_height)?];
1210
1211        #[derive(Deserialize)]
1212        struct Response {
1213            pub start_height: usize,
1214            pub stop_height: Option<usize>,
1215        }
1216        let res: Response =
1217            self.call("rescanblockchain", handle_defaults(&mut args, &[0.into(), null()]))?;
1218        Ok((res.start_height, res.stop_height))
1219    }
1220
1221    /// Returns statistics about the unspent transaction output set.
1222    /// Note this call may take some time if you are not using coinstatsindex.
1223    fn get_tx_out_set_info(
1224        &self,
1225        hash_type: Option<json::TxOutSetHashType>,
1226        hash_or_height: Option<json::HashOrHeight>,
1227        use_index: Option<bool>,
1228    ) -> Result<json::GetTxOutSetInfoResult> {
1229        let mut args =
1230            [opt_into_json(hash_type)?, opt_into_json(hash_or_height)?, opt_into_json(use_index)?];
1231        self.call("gettxoutsetinfo", handle_defaults(&mut args, &[null(), null(), null()]))
1232    }
1233
1234    /// Returns information about network traffic, including bytes in, bytes out,
1235    /// and current time.
1236    fn get_net_totals(&self) -> Result<json::GetNetTotalsResult> {
1237        self.call("getnettotals", &[])
1238    }
1239
1240    /// Returns the estimated network hashes per second based on the last n blocks.
1241    fn get_network_hash_ps(&self, nblocks: Option<u64>, height: Option<u64>) -> Result<f64> {
1242        let mut args = [opt_into_json(nblocks)?, opt_into_json(height)?];
1243        self.call("getnetworkhashps", handle_defaults(&mut args, &[null(), null()]))
1244    }
1245
1246    /// Returns the total uptime of the server in seconds
1247    fn uptime(&self) -> Result<u64> {
1248        self.call("uptime", &[])
1249    }
1250
1251    /// Submit a block
1252    fn submit_block(&self, block: &bitcoin::Block) -> Result<()> {
1253        let block_hex: String = bitcoin::consensus::encode::serialize_hex(block);
1254        self.submit_block_hex(&block_hex)
1255    }
1256
1257    /// Submit a raw block
1258    fn submit_block_bytes(&self, block_bytes: &[u8]) -> Result<()> {
1259        let block_hex: String = block_bytes.to_lower_hex_string();
1260        self.submit_block_hex(&block_hex)
1261    }
1262
1263    /// Submit a block as a hex string
1264    fn submit_block_hex(&self, block_hex: &str) -> Result<()> {
1265        match self.call("submitblock", &[into_json(&block_hex)?]) {
1266            Ok(serde_json::Value::Null) => Ok(()),
1267            Ok(res) => Err(Error::ReturnedError(res.to_string())),
1268            Err(err) => Err(err.into()),
1269        }
1270    }
1271
1272    fn scan_tx_out_set_blocking(
1273        &self,
1274        descriptors: &[json::ScanTxOutRequest],
1275    ) -> Result<json::ScanTxOutResult> {
1276        self.call("scantxoutset", &["start".into(), into_json(descriptors)?])
1277    }
1278}
1279
1280/// Client implements a JSON-RPC client for the Bitcoin Core daemon or compatible APIs.
1281pub struct Client {
1282    client: jsonrpc::client::Client,
1283}
1284
1285impl fmt::Debug for Client {
1286    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1287        write!(f, "bitcoincore_rpc::Client({:?})", self.client)
1288    }
1289}
1290
1291impl Client {
1292    /// Creates a client to a bitcoind JSON-RPC server.
1293    ///
1294    /// Can only return [Err] when using cookie authentication.
1295    pub fn new(url: &str, auth: Auth) -> Result<Self> {
1296        let (user, pass) = auth.get_user_pass()?;
1297        jsonrpc::client::Client::simple_http(url, user, pass)
1298            .map(|client| Client {
1299                client,
1300            })
1301            .map_err(|e| super::error::Error::JsonRpc(e.into()))
1302    }
1303
1304    pub fn new_minreq_http(url: &str, auth: Auth) -> Result<Self> {
1305        let (user, pass) = auth.get_user_pass()?;
1306        let mut tp_builder = Builder::new().timeout(Duration::from_millis(10000)).url(url).unwrap();
1307        if let Some(user) = user {
1308            tp_builder = tp_builder.basic_auth(user, pass);
1309        }
1310        let tp = tp_builder.build();
1311
1312        let client = jsonrpc::client::Client::with_transport(tp);
1313        Ok(Client {
1314            client,
1315        })
1316    }
1317
1318    /// Create a new Client using the given [jsonrpc::Client].
1319    pub fn from_jsonrpc(client: jsonrpc::client::Client) -> Client {
1320        Client {
1321            client,
1322        }
1323    }
1324
1325    /// Get the underlying JSONRPC client.
1326    pub fn get_jsonrpc_client(&self) -> &jsonrpc::client::Client {
1327        &self.client
1328    }
1329}
1330
1331impl RpcApi for Client {
1332    /// Call an `cmd` rpc with given `args` list
1333    fn call<T: for<'a> serde::de::Deserialize<'a>>(
1334        &self,
1335        cmd: &str,
1336        args: &[serde_json::Value],
1337    ) -> Result<T> {
1338        let raw_args: Vec<_> = args
1339            .iter()
1340            .map(|a| {
1341                let json_string = serde_json::to_string(a)?;
1342                serde_json::value::RawValue::from_string(json_string) // we can't use to_raw_value here due to compat with Rust 1.29
1343            })
1344            .map(|a| a.map_err(|e| Error::Json(e)))
1345            .collect::<Result<Vec<_>>>()?;
1346        let req = self.client.build_request(&cmd, &raw_args);
1347        if log_enabled!(Debug) {
1348            debug!(target: "bitcoincore_rpc", "JSON-RPC request: {} {}", cmd, serde_json::Value::from(args));
1349        }
1350
1351        let resp = self.client.send_request(req).map_err(Error::from);
1352        log_response(cmd, &resp);
1353        Ok(resp?.result()?)
1354    }
1355}
1356
1357fn log_response(cmd: &str, resp: &Result<jsonrpc::Response>) {
1358    if log_enabled!(Warn) || log_enabled!(Debug) || log_enabled!(Trace) {
1359        match resp {
1360            Err(ref e) => {
1361                if log_enabled!(Debug) {
1362                    debug!(target: "bitcoincore_rpc", "JSON-RPC failed parsing reply of {}: {:?}", cmd, e);
1363                }
1364            }
1365            Ok(ref resp) => {
1366                if let Some(ref e) = resp.error {
1367                    if log_enabled!(Debug) {
1368                        debug!(target: "bitcoincore_rpc", "JSON-RPC error for {}: {:?}", cmd, e);
1369                    }
1370                } else if log_enabled!(Trace) {
1371                    // we can't use to_raw_value here due to compat with Rust 1.29
1372                    let def = serde_json::value::RawValue::from_string(
1373                        serde_json::Value::Null.to_string(),
1374                    )
1375                    .unwrap();
1376                    let result = resp.result.as_ref().unwrap_or(&def);
1377                    trace!(target: "bitcoincore_rpc", "JSON-RPC response for {}: {}", cmd, result);
1378                }
1379            }
1380        }
1381    }
1382}
1383
1384#[cfg(test)]
1385mod tests {
1386    use super::*;
1387    use crate::bitcoin;
1388    use serde_json;
1389
1390    #[test]
1391    fn test_raw_tx() {
1392        use crate::bitcoin::consensus::encode;
1393        let client = Client::new("http://localhost/".into(), Auth::None).unwrap();
1394        let tx: bitcoin::Transaction = encode::deserialize(&Vec::<u8>::from_hex("0200000001586bd02815cf5faabfec986a4e50d25dbee089bd2758621e61c5fab06c334af0000000006b483045022100e85425f6d7c589972ee061413bcf08dc8c8e589ce37b217535a42af924f0e4d602205c9ba9cb14ef15513c9d946fa1c4b797883e748e8c32171bdf6166583946e35c012103dae30a4d7870cd87b45dd53e6012f71318fdd059c1c2623b8cc73f8af287bb2dfeffffff021dc4260c010000001976a914f602e88b2b5901d8aab15ebe4a97cf92ec6e03b388ac00e1f505000000001976a914687ffeffe8cf4e4c038da46a9b1d37db385a472d88acfd211500").unwrap()).unwrap();
1395
1396        assert!(client.send_raw_transaction(&tx).is_err());
1397        assert!(client.send_raw_transaction(&encode::serialize(&tx)).is_err());
1398        assert!(client.send_raw_transaction("deadbeef").is_err());
1399        assert!(client.send_raw_transaction("deadbeef".to_owned()).is_err());
1400    }
1401
1402    fn test_handle_defaults_inner() -> Result<()> {
1403        {
1404            let mut args = [into_json(0)?, null(), null()];
1405            let defaults = [into_json(1)?, into_json(2)?];
1406            let res = [into_json(0)?];
1407            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1408        }
1409        {
1410            let mut args = [into_json(0)?, into_json(1)?, null()];
1411            let defaults = [into_json(2)?];
1412            let res = [into_json(0)?, into_json(1)?];
1413            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1414        }
1415        {
1416            let mut args = [into_json(0)?, null(), into_json(5)?];
1417            let defaults = [into_json(2)?, into_json(3)?];
1418            let res = [into_json(0)?, into_json(2)?, into_json(5)?];
1419            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1420        }
1421        {
1422            let mut args = [into_json(0)?, null(), into_json(5)?, null()];
1423            let defaults = [into_json(2)?, into_json(3)?, into_json(4)?];
1424            let res = [into_json(0)?, into_json(2)?, into_json(5)?];
1425            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1426        }
1427        {
1428            let mut args = [null(), null()];
1429            let defaults = [into_json(2)?, into_json(3)?];
1430            let res: [serde_json::Value; 0] = [];
1431            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1432        }
1433        {
1434            let mut args = [null(), into_json(1)?];
1435            let defaults = [];
1436            let res = [null(), into_json(1)?];
1437            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1438        }
1439        {
1440            let mut args = [];
1441            let defaults = [];
1442            let res: [serde_json::Value; 0] = [];
1443            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1444        }
1445        {
1446            let mut args = [into_json(0)?];
1447            let defaults = [into_json(2)?];
1448            let res = [into_json(0)?];
1449            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1450        }
1451        Ok(())
1452    }
1453
1454    #[test]
1455    fn test_handle_defaults() {
1456        test_handle_defaults_inner().unwrap();
1457    }
1458
1459    #[test]
1460    fn auth_cookie_file_ignores_newline() {
1461        let tempdir = tempfile::tempdir().unwrap();
1462        let path = tempdir.path().join("cookie");
1463        std::fs::write(&path, "foo:bar\n").unwrap();
1464        assert_eq!(
1465            Auth::CookieFile(path).get_user_pass().unwrap(),
1466            (Some("foo".into()), Some("bar".into())),
1467        );
1468    }
1469
1470    #[test]
1471    fn auth_cookie_file_ignores_additional_lines() {
1472        let tempdir = tempfile::tempdir().unwrap();
1473        let path = tempdir.path().join("cookie");
1474        std::fs::write(&path, "foo:bar\nbaz").unwrap();
1475        assert_eq!(
1476            Auth::CookieFile(path).get_user_pass().unwrap(),
1477            (Some("foo".into()), Some("bar".into())),
1478        );
1479    }
1480
1481    #[test]
1482    fn auth_cookie_file_fails_if_colon_isnt_present() {
1483        let tempdir = tempfile::tempdir().unwrap();
1484        let path = tempdir.path().join("cookie");
1485        std::fs::write(&path, "foobar").unwrap();
1486        assert!(matches!(Auth::CookieFile(path).get_user_pass(), Err(Error::InvalidCookieFile)));
1487    }
1488}