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::iter::FromIterator;
14use std::path::PathBuf;
15use std::{fmt, result};
16
17use crate::{bitcoin, deserialize_hex};
18use bitcoin_private::hex::exts::DisplayHex;
19use jsonrpc;
20use serde;
21use serde_json;
22
23use crate::bitcoin::address::{NetworkUnchecked, NetworkChecked};
24use crate::bitcoin::hashes::hex::FromHex;
25use crate::bitcoin::secp256k1::ecdsa::Signature;
26use crate::bitcoin::{
27    Address, Amount, Block, OutPoint, PrivateKey, PublicKey, Script, Transaction,
28};
29use log::Level::{Debug, Trace, Warn};
30
31use crate::error::*;
32use crate::json;
33use crate::queryable;
34
35/// Crate-specific Result type, shorthand for `std::result::Result` with our
36/// crate-specific Error type;
37pub type Result<T> = result::Result<T, Error>;
38
39/// Outpoint that serializes and deserializes as a map, instead of a string,
40/// for use as RPC arguments
41#[derive(Clone, Debug, Serialize, Deserialize)]
42pub struct JsonOutPoint {
43    pub txid: bitcoin::Txid,
44    pub vout: u32,
45}
46
47impl From<OutPoint> for JsonOutPoint {
48    fn from(o: OutPoint) -> JsonOutPoint {
49        JsonOutPoint {
50            txid: o.txid,
51            vout: o.vout,
52        }
53    }
54}
55
56impl Into<OutPoint> for JsonOutPoint {
57    fn into(self) -> OutPoint {
58        OutPoint {
59            txid: self.txid,
60            vout: self.vout,
61        }
62    }
63}
64
65/// Shorthand for converting a variable into a serde_json::Value.
66fn into_json<T>(val: T) -> Result<serde_json::Value>
67where
68    T: serde::ser::Serialize,
69{
70    Ok(serde_json::to_value(val)?)
71}
72
73/// Shorthand for converting an Option into an Option<serde_json::Value>.
74fn opt_into_json<T>(opt: Option<T>) -> Result<serde_json::Value>
75where
76    T: serde::ser::Serialize,
77{
78    match opt {
79        Some(val) => Ok(into_json(val)?),
80        None => Ok(serde_json::Value::Null),
81    }
82}
83
84/// Shorthand for `serde_json::Value::Null`.
85fn null() -> serde_json::Value {
86    serde_json::Value::Null
87}
88
89/// Shorthand for an empty serde_json::Value array.
90fn empty_arr() -> serde_json::Value {
91    serde_json::Value::Array(vec![])
92}
93
94/// Shorthand for an empty serde_json object.
95fn empty_obj() -> serde_json::Value {
96    serde_json::Value::Object(Default::default())
97}
98
99/// Handle default values in the argument list
100///
101/// Substitute `Value::Null`s with corresponding values from `defaults` table,
102/// except when they are trailing, in which case just skip them altogether
103/// in returned list.
104///
105/// Note, that `defaults` corresponds to the last elements of `args`.
106///
107/// ```norust
108/// arg1 arg2 arg3 arg4
109///           def1 def2
110/// ```
111///
112/// Elements of `args` without corresponding `defaults` value, won't
113/// be substituted, because they are required.
114fn handle_defaults<'a, 'b>(
115    args: &'a mut [serde_json::Value],
116    defaults: &'b [serde_json::Value],
117) -> &'a [serde_json::Value] {
118    assert!(args.len() >= defaults.len());
119
120    // Pass over the optional arguments in backwards order, filling in defaults after the first
121    // non-null optional argument has been observed.
122    let mut first_non_null_optional_idx = None;
123    for i in 0..defaults.len() {
124        let args_i = args.len() - 1 - i;
125        let defaults_i = defaults.len() - 1 - i;
126        if args[args_i] == serde_json::Value::Null {
127            if first_non_null_optional_idx.is_some() {
128                if defaults[defaults_i] == serde_json::Value::Null {
129                    panic!("Missing `default` for argument idx {}", args_i);
130                }
131                args[args_i] = defaults[defaults_i].clone();
132            }
133        } else if first_non_null_optional_idx.is_none() {
134            first_non_null_optional_idx = Some(args_i);
135        }
136    }
137
138    let required_num = args.len() - defaults.len();
139
140    if let Some(i) = first_non_null_optional_idx {
141        &args[..i + 1]
142    } else {
143        &args[..required_num]
144    }
145}
146
147/// Convert a possible-null result into an Option.
148fn opt_result<T: for<'a> serde::de::Deserialize<'a>>(
149    result: serde_json::Value,
150) -> Result<Option<T>> {
151    if result == serde_json::Value::Null {
152        Ok(None)
153    } else {
154        Ok(serde_json::from_value(result)?)
155    }
156}
157
158/// Used to pass raw txs into the API.
159pub trait RawTx: Sized + Clone {
160    fn raw_hex(self) -> String;
161}
162
163impl<'a> RawTx for &'a Transaction {
164    fn raw_hex(self) -> String {
165        bitcoin::consensus::encode::serialize_hex(self)
166    }
167}
168
169impl<'a> RawTx for &'a [u8] {
170    fn raw_hex(self) -> String {
171        self.to_lower_hex_string()
172    }
173}
174
175impl<'a> RawTx for &'a Vec<u8> {
176    fn raw_hex(self) -> String {
177        self.to_lower_hex_string()
178    }
179}
180
181impl<'a> RawTx for &'a str {
182    fn raw_hex(self) -> String {
183        self.to_owned()
184    }
185}
186
187impl RawTx for String {
188    fn raw_hex(self) -> String {
189        self
190    }
191}
192
193/// The different authentication methods for the client.
194#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
195pub enum Auth {
196    None,
197    UserPass(String, String),
198    CookieFile(PathBuf),
199}
200
201impl Auth {
202    /// Convert into the arguments that jsonrpc::Client needs.
203    pub fn get_user_pass(self) -> Result<(Option<String>, Option<String>)> {
204        use std::io::Read;
205        match self {
206            Auth::None => Ok((None, None)),
207            Auth::UserPass(u, p) => Ok((Some(u), Some(p))),
208            Auth::CookieFile(path) => {
209                let mut file = File::open(path)?;
210                let mut contents = String::new();
211                file.read_to_string(&mut contents)?;
212                let mut split = contents.splitn(2, ":");
213                Ok((
214                    Some(split.next().ok_or(Error::InvalidCookieFile)?.into()),
215                    Some(split.next().ok_or(Error::InvalidCookieFile)?.into()),
216                ))
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(&self, address_type: Option<json::AddressType>) -> Result<Address<NetworkUnchecked>> {
902        self.call("getrawchangeaddress", &[opt_into_json(address_type)?])
903    }
904
905    fn get_address_info(&self, address: &Address) -> Result<json::GetAddressInfoResult> {
906        self.call("getaddressinfo", &[address.to_string().into()])
907    }
908
909    /// Mine `block_num` blocks and pay coinbase to `address`
910    ///
911    /// Returns hashes of the generated blocks
912    fn generate_to_address(
913        &self,
914        block_num: u64,
915        address: &Address<NetworkChecked>,
916    ) -> Result<Vec<bitcoin::BlockHash>> {
917        self.call("generatetoaddress", &[block_num.into(), address.to_string().into()])
918    }
919
920    /// Mine up to block_num blocks immediately (before the RPC call returns)
921    /// to an address in the wallet.
922    fn generate(&self, block_num: u64, maxtries: Option<u64>) -> Result<Vec<bitcoin::BlockHash>> {
923        self.call("generate", &[block_num.into(), opt_into_json(maxtries)?])
924    }
925
926    /// Mark a block as invalid by `block_hash`
927    fn invalidate_block(&self, block_hash: &bitcoin::BlockHash) -> Result<()> {
928        self.call("invalidateblock", &[into_json(block_hash)?])
929    }
930
931    /// Mark a block as valid by `block_hash`
932    fn reconsider_block(&self, block_hash: &bitcoin::BlockHash) -> Result<()> {
933        self.call("reconsiderblock", &[into_json(block_hash)?])
934    }
935
936    /// Returns details on the active state of the TX memory pool
937    fn get_mempool_info(&self) -> Result<json::GetMempoolInfoResult> {
938        self.call("getmempoolinfo", &[])
939    }
940
941    /// Get txids of all transactions in a memory pool
942    fn get_raw_mempool(&self) -> Result<Vec<bitcoin::Txid>> {
943        self.call("getrawmempool", &[])
944    }
945
946    /// Get details for the transactions in a memory pool
947    fn get_raw_mempool_verbose(
948        &self,
949    ) -> Result<HashMap<bitcoin::Txid, json::GetMempoolEntryResult>> {
950        self.call("getrawmempool", &[into_json(true)?])
951    }
952
953    /// Get mempool data for given transaction
954    fn get_mempool_entry(&self, txid: &bitcoin::Txid) -> Result<json::GetMempoolEntryResult> {
955        self.call("getmempoolentry", &[into_json(txid)?])
956    }
957
958    /// Get information about all known tips in the block tree, including the
959    /// main chain as well as stale branches.
960    fn get_chain_tips(&self) -> Result<json::GetChainTipsResult> {
961        self.call("getchaintips", &[])
962    }
963
964    fn send_to_address(
965        &self,
966        address: &Address<NetworkChecked>,
967        amount: Amount,
968        comment: Option<&str>,
969        comment_to: Option<&str>,
970        subtract_fee: Option<bool>,
971        replaceable: Option<bool>,
972        confirmation_target: Option<u32>,
973        estimate_mode: Option<json::EstimateMode>,
974    ) -> Result<bitcoin::Txid> {
975        let mut args = [
976            address.to_string().into(),
977            into_json(amount.to_btc())?,
978            opt_into_json(comment)?,
979            opt_into_json(comment_to)?,
980            opt_into_json(subtract_fee)?,
981            opt_into_json(replaceable)?,
982            opt_into_json(confirmation_target)?,
983            opt_into_json(estimate_mode)?,
984        ];
985        self.call(
986            "sendtoaddress",
987            handle_defaults(
988                &mut args,
989                &["".into(), "".into(), false.into(), false.into(), 6.into(), null()],
990            ),
991        )
992    }
993
994    /// Attempts to add a node to the addnode list.
995    /// 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).
996    fn add_node(&self, addr: &str) -> Result<()> {
997        self.call("addnode", &[into_json(&addr)?, into_json("add")?])
998    }
999
1000    /// Attempts to remove a node from the addnode list.
1001    fn remove_node(&self, addr: &str) -> Result<()> {
1002        self.call("addnode", &[into_json(&addr)?, into_json("remove")?])
1003    }
1004
1005    /// Attempts to connect to a node without permanently adding it to the addnode list.
1006    fn onetry_node(&self, addr: &str) -> Result<()> {
1007        self.call("addnode", &[into_json(&addr)?, into_json("onetry")?])
1008    }
1009
1010    /// Immediately disconnects from the specified peer node.
1011    fn disconnect_node(&self, addr: &str) -> Result<()> {
1012        self.call("disconnectnode", &[into_json(&addr)?])
1013    }
1014
1015    fn disconnect_node_by_id(&self, node_id: u32) -> Result<()> {
1016        self.call("disconnectnode", &[into_json("")?, into_json(node_id)?])
1017    }
1018
1019    /// Returns information about the given added node, or all added nodes (note that onetry addnodes are not listed here)
1020    fn get_added_node_info(&self, node: Option<&str>) -> Result<Vec<json::GetAddedNodeInfoResult>> {
1021        if let Some(addr) = node {
1022            self.call("getaddednodeinfo", &[into_json(&addr)?])
1023        } else {
1024            self.call("getaddednodeinfo", &[])
1025        }
1026    }
1027
1028    /// Return known addresses which can potentially be used to find new nodes in the network
1029    fn get_node_addresses(
1030        &self,
1031        count: Option<usize>,
1032    ) -> Result<Vec<json::GetNodeAddressesResult>> {
1033        let cnt = count.unwrap_or(1);
1034        self.call("getnodeaddresses", &[into_json(&cnt)?])
1035    }
1036
1037    /// List all banned IPs/Subnets.
1038    fn list_banned(&self) -> Result<Vec<json::ListBannedResult>> {
1039        self.call("listbanned", &[])
1040    }
1041
1042    /// Clear all banned IPs.
1043    fn clear_banned(&self) -> Result<()> {
1044        self.call("clearbanned", &[])
1045    }
1046
1047    /// Attempts to add an IP/Subnet to the banned list.
1048    fn add_ban(&self, subnet: &str, bantime: u64, absolute: bool) -> Result<()> {
1049        self.call(
1050            "setban",
1051            &[into_json(&subnet)?, into_json("add")?, into_json(&bantime)?, into_json(&absolute)?],
1052        )
1053    }
1054
1055    /// Attempts to remove an IP/Subnet from the banned list.
1056    fn remove_ban(&self, subnet: &str) -> Result<()> {
1057        self.call("setban", &[into_json(&subnet)?, into_json("remove")?])
1058    }
1059
1060    /// Disable/enable all p2p network activity.
1061    fn set_network_active(&self, state: bool) -> Result<bool> {
1062        self.call("setnetworkactive", &[into_json(&state)?])
1063    }
1064
1065    /// Returns data about each connected network node as an array of
1066    /// [`PeerInfo`][]
1067    ///
1068    /// [`PeerInfo`]: net/struct.PeerInfo.html
1069    fn get_peer_info(&self) -> Result<Vec<json::GetPeerInfoResult>> {
1070        self.call("getpeerinfo", &[])
1071    }
1072
1073    /// Requests that a ping be sent to all other nodes, to measure ping
1074    /// time.
1075    ///
1076    /// Results provided in `getpeerinfo`, `pingtime` and `pingwait` fields
1077    /// are decimal seconds.
1078    ///
1079    /// Ping command is handled in queue with all other commands, so it
1080    /// measures processing backlog, not just network ping.
1081    fn ping(&self) -> Result<()> {
1082        self.call("ping", &[])
1083    }
1084
1085    fn send_raw_transaction<R: RawTx>(&self, tx: R) -> Result<bitcoin::Txid> {
1086        self.call("sendrawtransaction", &[tx.raw_hex().into()])
1087    }
1088
1089    fn estimate_smart_fee(
1090        &self,
1091        conf_target: u16,
1092        estimate_mode: Option<json::EstimateMode>,
1093    ) -> Result<json::EstimateSmartFeeResult> {
1094        let mut args = [into_json(conf_target)?, opt_into_json(estimate_mode)?];
1095        self.call("estimatesmartfee", handle_defaults(&mut args, &[null()]))
1096    }
1097
1098    /// Waits for a specific new block and returns useful info about it.
1099    /// Returns the current block on timeout or exit.
1100    ///
1101    /// # Arguments
1102    ///
1103    /// 1. `timeout`: Time in milliseconds to wait for a response. 0
1104    /// indicates no timeout.
1105    fn wait_for_new_block(&self, timeout: u64) -> Result<json::BlockRef> {
1106        self.call("waitfornewblock", &[into_json(timeout)?])
1107    }
1108
1109    /// Waits for a specific new block and returns useful info about it.
1110    /// Returns the current block on timeout or exit.
1111    ///
1112    /// # Arguments
1113    ///
1114    /// 1. `blockhash`: Block hash to wait for.
1115    /// 2. `timeout`: Time in milliseconds to wait for a response. 0
1116    /// indicates no timeout.
1117    fn wait_for_block(
1118        &self,
1119        blockhash: &bitcoin::BlockHash,
1120        timeout: u64,
1121    ) -> Result<json::BlockRef> {
1122        let args = [into_json(blockhash)?, into_json(timeout)?];
1123        self.call("waitforblock", &args)
1124    }
1125
1126    fn wallet_create_funded_psbt(
1127        &self,
1128        inputs: &[json::CreateRawTransactionInput],
1129        outputs: &HashMap<String, Amount>,
1130        locktime: Option<i64>,
1131        options: Option<json::WalletCreateFundedPsbtOptions>,
1132        bip32derivs: Option<bool>,
1133    ) -> Result<json::WalletCreateFundedPsbtResult> {
1134        let outputs_converted = serde_json::Map::from_iter(
1135            outputs.iter().map(|(k, v)| (k.clone(), serde_json::Value::from(v.to_btc()))),
1136        );
1137        let mut args = [
1138            into_json(inputs)?,
1139            into_json(outputs_converted)?,
1140            opt_into_json(locktime)?,
1141            opt_into_json(options)?,
1142            opt_into_json(bip32derivs)?,
1143        ];
1144        self.call(
1145            "walletcreatefundedpsbt",
1146            handle_defaults(&mut args, &[0.into(), serde_json::Map::new().into(), false.into()]),
1147        )
1148    }
1149
1150    fn wallet_process_psbt(
1151        &self,
1152        psbt: &str,
1153        sign: Option<bool>,
1154        sighash_type: Option<json::SigHashType>,
1155        bip32derivs: Option<bool>,
1156    ) -> Result<json::WalletProcessPsbtResult> {
1157        let mut args = [
1158            into_json(psbt)?,
1159            opt_into_json(sign)?,
1160            opt_into_json(sighash_type)?,
1161            opt_into_json(bip32derivs)?,
1162        ];
1163        let defaults = [
1164            true.into(),
1165            into_json(json::SigHashType::from(bitcoin::sighash::EcdsaSighashType::All))?,
1166            true.into(),
1167        ];
1168        self.call("walletprocesspsbt", handle_defaults(&mut args, &defaults))
1169    }
1170
1171    fn get_descriptor_info(&self, desc: &str) -> Result<json::GetDescriptorInfoResult> {
1172        self.call("getdescriptorinfo", &[desc.to_string().into()])
1173    }
1174
1175    fn join_psbt(&self, psbts: &[String]) -> Result<String> {
1176        self.call("joinpsbts", &[into_json(psbts)?])
1177    }
1178
1179    fn combine_psbt(&self, psbts: &[String]) -> Result<String> {
1180        self.call("combinepsbt", &[into_json(psbts)?])
1181    }
1182
1183    fn combine_raw_transaction(&self, hex_strings: &[String]) -> Result<String> {
1184        self.call("combinerawtransaction", &[into_json(hex_strings)?])
1185    }
1186
1187    fn finalize_psbt(&self, psbt: &str, extract: Option<bool>) -> Result<json::FinalizePsbtResult> {
1188        let mut args = [into_json(psbt)?, opt_into_json(extract)?];
1189        self.call("finalizepsbt", handle_defaults(&mut args, &[true.into()]))
1190    }
1191
1192    fn derive_addresses(&self, descriptor: &str, range: Option<[u32; 2]>) -> Result<Vec<Address<NetworkUnchecked>>> {
1193        let mut args = [into_json(descriptor)?, opt_into_json(range)?];
1194        self.call("deriveaddresses", handle_defaults(&mut args, &[null()]))
1195    }
1196
1197    fn rescan_blockchain(
1198        &self,
1199        start_from: Option<usize>,
1200        stop_height: Option<usize>,
1201    ) -> Result<(usize, Option<usize>)> {
1202        let mut args = [opt_into_json(start_from)?, opt_into_json(stop_height)?];
1203
1204        #[derive(Deserialize)]
1205        struct Response {
1206            pub start_height: usize,
1207            pub stop_height: Option<usize>,
1208        }
1209        let res: Response =
1210            self.call("rescanblockchain", handle_defaults(&mut args, &[0.into(), null()]))?;
1211        Ok((res.start_height, res.stop_height))
1212    }
1213
1214    /// Returns statistics about the unspent transaction output set.
1215    /// Note this call may take some time if you are not using coinstatsindex.
1216    fn get_tx_out_set_info(
1217        &self,
1218        hash_type: Option<json::TxOutSetHashType>,
1219        hash_or_height: Option<json::HashOrHeight>,
1220        use_index: Option<bool>,
1221    ) -> Result<json::GetTxOutSetInfoResult> {
1222        let mut args =
1223            [opt_into_json(hash_type)?, opt_into_json(hash_or_height)?, opt_into_json(use_index)?];
1224        self.call("gettxoutsetinfo", handle_defaults(&mut args, &[null(), null(), null()]))
1225    }
1226
1227    /// Returns information about network traffic, including bytes in, bytes out,
1228    /// and current time.
1229    fn get_net_totals(&self) -> Result<json::GetNetTotalsResult> {
1230        self.call("getnettotals", &[])
1231    }
1232
1233    /// Returns the estimated network hashes per second based on the last n blocks.
1234    fn get_network_hash_ps(&self, nblocks: Option<u64>, height: Option<u64>) -> Result<f64> {
1235        let mut args = [opt_into_json(nblocks)?, opt_into_json(height)?];
1236        self.call("getnetworkhashps", handle_defaults(&mut args, &[null(), null()]))
1237    }
1238
1239    /// Returns the total uptime of the server in seconds
1240    fn uptime(&self) -> Result<u64> {
1241        self.call("uptime", &[])
1242    }
1243
1244    /// Submit a block
1245    fn submit_block(&self, block: &bitcoin::Block) -> Result<()> {
1246        let block_hex: String = bitcoin::consensus::encode::serialize_hex(block);
1247        self.submit_block_hex(&block_hex)
1248    }
1249
1250    /// Submit a raw block
1251    fn submit_block_bytes(&self, block_bytes: &[u8]) -> Result<()> {
1252        let block_hex: String = block_bytes.to_lower_hex_string();
1253        self.submit_block_hex(&block_hex)
1254    }
1255
1256    /// Submit a block as a hex string
1257    fn submit_block_hex(&self, block_hex: &str) -> Result<()> {
1258        match self.call("submitblock", &[into_json(&block_hex)?]) {
1259            Ok(serde_json::Value::Null) => Ok(()),
1260            Ok(res) => Err(Error::ReturnedError(res.to_string())),
1261            Err(err) => Err(err.into()),
1262        }
1263    }
1264
1265    fn scan_tx_out_set_blocking(
1266        &self,
1267        descriptors: &[json::ScanTxOutRequest],
1268    ) -> Result<json::ScanTxOutResult> {
1269        self.call("scantxoutset", &["start".into(), into_json(descriptors)?])
1270    }
1271}
1272
1273/// Client implements a JSON-RPC client for the Bitcoin Core daemon or compatible APIs.
1274pub struct Client {
1275    client: jsonrpc::client::Client,
1276}
1277
1278impl fmt::Debug for Client {
1279    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1280        write!(f, "bitcoincore_rpc::Client({:?})", self.client)
1281    }
1282}
1283
1284impl Client {
1285    /// Creates a client to a bitcoind JSON-RPC server.
1286    ///
1287    /// Can only return [Err] when using cookie authentication.
1288    pub fn new(url: &str, auth: Auth) -> Result<Self> {
1289        let (user, pass) = auth.get_user_pass()?;
1290        jsonrpc::client::Client::simple_http(url, user, pass)
1291            .map(|client| Client {
1292                client,
1293            })
1294            .map_err(|e| super::error::Error::JsonRpc(e.into()))
1295    }
1296
1297    /// Create a new Client using the given [jsonrpc::Client].
1298    pub fn from_jsonrpc(client: jsonrpc::client::Client) -> Client {
1299        Client {
1300            client,
1301        }
1302    }
1303
1304    /// Get the underlying JSONRPC client.
1305    pub fn get_jsonrpc_client(&self) -> &jsonrpc::client::Client {
1306        &self.client
1307    }
1308}
1309
1310impl RpcApi for Client {
1311    /// Call an `cmd` rpc with given `args` list
1312    fn call<T: for<'a> serde::de::Deserialize<'a>>(
1313        &self,
1314        cmd: &str,
1315        args: &[serde_json::Value],
1316    ) -> Result<T> {
1317        let raw_args: Vec<_> = args
1318            .iter()
1319            .map(|a| {
1320                let json_string = serde_json::to_string(a)?;
1321                serde_json::value::RawValue::from_string(json_string) // we can't use to_raw_value here due to compat with Rust 1.29
1322            })
1323            .map(|a| a.map_err(|e| Error::Json(e)))
1324            .collect::<Result<Vec<_>>>()?;
1325        let req = self.client.build_request(&cmd, &raw_args);
1326        if log_enabled!(Debug) {
1327            debug!(target: "bitcoincore_rpc", "JSON-RPC request: {} {}", cmd, serde_json::Value::from(args));
1328        }
1329
1330        let resp = self.client.send_request(req).map_err(Error::from);
1331        log_response(cmd, &resp);
1332        Ok(resp?.result()?)
1333    }
1334}
1335
1336fn log_response(cmd: &str, resp: &Result<jsonrpc::Response>) {
1337    if log_enabled!(Warn) || log_enabled!(Debug) || log_enabled!(Trace) {
1338        match resp {
1339            Err(ref e) => {
1340                if log_enabled!(Debug) {
1341                    debug!(target: "bitcoincore_rpc", "JSON-RPC failed parsing reply of {}: {:?}", cmd, e);
1342                }
1343            }
1344            Ok(ref resp) => {
1345                if let Some(ref e) = resp.error {
1346                    if log_enabled!(Debug) {
1347                        debug!(target: "bitcoincore_rpc", "JSON-RPC error for {}: {:?}", cmd, e);
1348                    }
1349                } else if log_enabled!(Trace) {
1350                    // we can't use to_raw_value here due to compat with Rust 1.29
1351                    let def = serde_json::value::RawValue::from_string(
1352                        serde_json::Value::Null.to_string(),
1353                    )
1354                    .unwrap();
1355                    let result = resp.result.as_ref().unwrap_or(&def);
1356                    trace!(target: "bitcoincore_rpc", "JSON-RPC response for {}: {}", cmd, result);
1357                }
1358            }
1359        }
1360    }
1361}
1362
1363#[cfg(test)]
1364mod tests {
1365    use super::*;
1366    use crate::bitcoin;
1367    use serde_json;
1368
1369    #[test]
1370    fn test_raw_tx() {
1371        use crate::bitcoin::consensus::encode;
1372        let client = Client::new("http://localhost/".into(), Auth::None).unwrap();
1373        let tx: bitcoin::Transaction = encode::deserialize(&Vec::<u8>::from_hex("0200000001586bd02815cf5faabfec986a4e50d25dbee089bd2758621e61c5fab06c334af0000000006b483045022100e85425f6d7c589972ee061413bcf08dc8c8e589ce37b217535a42af924f0e4d602205c9ba9cb14ef15513c9d946fa1c4b797883e748e8c32171bdf6166583946e35c012103dae30a4d7870cd87b45dd53e6012f71318fdd059c1c2623b8cc73f8af287bb2dfeffffff021dc4260c010000001976a914f602e88b2b5901d8aab15ebe4a97cf92ec6e03b388ac00e1f505000000001976a914687ffeffe8cf4e4c038da46a9b1d37db385a472d88acfd211500").unwrap()).unwrap();
1374
1375        assert!(client.send_raw_transaction(&tx).is_err());
1376        assert!(client.send_raw_transaction(&encode::serialize(&tx)).is_err());
1377        assert!(client.send_raw_transaction("deadbeef").is_err());
1378        assert!(client.send_raw_transaction("deadbeef".to_owned()).is_err());
1379    }
1380
1381    fn test_handle_defaults_inner() -> Result<()> {
1382        {
1383            let mut args = [into_json(0)?, null(), null()];
1384            let defaults = [into_json(1)?, into_json(2)?];
1385            let res = [into_json(0)?];
1386            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1387        }
1388        {
1389            let mut args = [into_json(0)?, into_json(1)?, null()];
1390            let defaults = [into_json(2)?];
1391            let res = [into_json(0)?, into_json(1)?];
1392            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1393        }
1394        {
1395            let mut args = [into_json(0)?, null(), into_json(5)?];
1396            let defaults = [into_json(2)?, into_json(3)?];
1397            let res = [into_json(0)?, into_json(2)?, into_json(5)?];
1398            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1399        }
1400        {
1401            let mut args = [into_json(0)?, null(), into_json(5)?, null()];
1402            let defaults = [into_json(2)?, into_json(3)?, into_json(4)?];
1403            let res = [into_json(0)?, into_json(2)?, into_json(5)?];
1404            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1405        }
1406        {
1407            let mut args = [null(), null()];
1408            let defaults = [into_json(2)?, into_json(3)?];
1409            let res: [serde_json::Value; 0] = [];
1410            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1411        }
1412        {
1413            let mut args = [null(), into_json(1)?];
1414            let defaults = [];
1415            let res = [null(), into_json(1)?];
1416            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1417        }
1418        {
1419            let mut args = [];
1420            let defaults = [];
1421            let res: [serde_json::Value; 0] = [];
1422            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1423        }
1424        {
1425            let mut args = [into_json(0)?];
1426            let defaults = [into_json(2)?];
1427            let res = [into_json(0)?];
1428            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1429        }
1430        Ok(())
1431    }
1432
1433    #[test]
1434    fn test_handle_defaults() {
1435        test_handle_defaults_inner().unwrap();
1436    }
1437}