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