LCOV - code coverage report
Current view: top level - src/rpc - client.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 24 38 63.2 %
Date: 2025-02-23 09:33:43 Functions: 4 6 66.7 %

          Line data    Source code
       1             : // Copyright (c) 2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin developers
       3             : // Copyright (c) 2014-2015 The Dash developers
       4             : // Copyright (c) 2015-2022 The PIVX Core developers
       5             : // Distributed under the MIT software license, see the accompanying
       6             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       7             : 
       8             : #include "rpc/client.h"
       9             : 
      10             : #include <set>
      11             : #include <stdint.h>
      12             : 
      13             : 
      14             : class CRPCConvertParam
      15             : {
      16             : public:
      17             :     std::string methodName; //! method whose params want conversion
      18             :     int paramIdx;           //! 0-based idx of param to convert
      19             :     std::string paramName; //!< parameter name
      20             : };
      21             : 
      22             : // clang-format off
      23             : /**
      24             :  * Specify a (method, idx, name) here if the argument is a non-string RPC
      25             :  * argument and needs to be converted from JSON.
      26             :  *
      27             :  * @note Parameter indexes start from 0.
      28             :  */
      29             : static const CRPCConvertParam vRPCConvertParams[] = {
      30             :     { "addmultisigaddress", 0, "nrequired" },
      31             :     { "addmultisigaddress", 1, "keys" },
      32             :     { "addpeeraddress", 1, "port" },
      33             :     { "cleanbudget", 0, "try_sync" },
      34             :     { "createmultisig", 0, "nrequired" },
      35             :     { "createmultisig", 1, "keys" },
      36             :     { "createrawtransaction", 0, "inputs" },
      37             :     { "createrawtransaction", 1, "outputs" },
      38             :     { "createrawtransaction", 2, "locktime" },
      39             :     { "createrawmnfinalbudget", 1, "blockstart" },
      40             :     { "createrawmnfinalbudget", 2, "proposals" },
      41             :     { "delegatestake", 1, "amount" },
      42             :     { "delegatestake", 3, "ext_owner" },
      43             :     { "delegatestake", 4, "include_delegated" },
      44             :     { "delegatestake", 5, "from_shield" },
      45             :     { "estimatefee", 0, "nblocks" },
      46             :     { "estimatesmartfee", 0, "nblocks" },
      47             :     { "fundrawtransaction", 1, "options" },
      48             :     { "generate", 0, "nblocks" },
      49             :     { "generatetoaddress", 0, "nblocks" },
      50             :     { "getaddednodeinfo", 0, "dummy" },
      51             :     { "getbalance", 0, "minconf" },
      52             :     { "getbalance", 1, "include_watchonly" },
      53             :     { "getbalance", 2, "include_delegated" },
      54             :     { "getbalance", 3, "include_shield" },
      55             :     { "getblock", 1, "verbosity" },
      56             :     { "getblock", 1, "verbose" },
      57             :     { "getblockhash", 0, "height" },
      58             :     { "getblockheader", 1, "verbose" },
      59             :     { "getblockindexstats", 0, "height" },
      60             :     { "getblockindexstats", 1, "range" },
      61             :     { "getblocktemplate", 0, "template_request" },
      62             :     { "getfeeinfo", 0, "blocks" },
      63             :     { "getshieldbalance", 1, "minconf" },
      64             :     { "getshieldbalance", 2, "include_watchonly" },
      65             :     { "getminedcommitment", 0, "llmq_type" },
      66             :     { "getnetworkhashps", 0, "nblocks" },
      67             :     { "getnetworkhashps", 1, "height" },
      68             :     { "getnodeaddresses", 0, "count" },
      69             :     { "getquorummembers", 0, "llmq_type" },
      70             :     { "getrawmempool", 0, "verbose" },
      71             :     { "getrawtransaction", 1, "verbose" },
      72             :     { "getreceivedbyaddress", 1, "minconf" },
      73             :     { "getreceivedbylabel", 1, "minconf" },
      74             :     { "getsaplingnotescount", 0, "minconf" },
      75             :     { "getsupplyinfo", 0, "force_update" },
      76             :     { "gettransaction", 1, "include_watchonly" },
      77             :     { "gettxout", 1, "n" },
      78             :     { "gettxout", 2, "include_mempool" },
      79             :     { "importaddress", 2, "rescan" },
      80             :     { "importaddress", 3, "p2sh" },
      81             :     { "importmulti", 0, "requests" },
      82             :     { "importmulti", 1, "options" },
      83             :     { "importprivkey", 2, "rescan" },
      84             :     { "importprivkey", 3, "is_staking_address" },
      85             :     { "importpubkey", 2, "rescan" },
      86             :     { "importsaplingkey", 1, "rescan" },
      87             :     { "importsaplingkey", 2, "height" },
      88             :     { "importsaplingviewingkey", 1, "rescan" },
      89             :     { "importsaplingviewingkey", 2, "height" },
      90             :     { "initmasternode", 2, "deterministic" },
      91             :     { "keypoolrefill", 0, "newsize" },
      92             :     { "listcoldutxos", 0, "not_whitelisted" },
      93             :     { "listdelegators", 0, "blacklist" },
      94             :     { "listreceivedbyaddress", 0, "minconf" },
      95             :     { "listreceivedbyaddress", 1, "include_empty" },
      96             :     { "listreceivedbyaddress", 2, "include_watchonly" },
      97             :     { "listreceivedbylabel", 0, "minconf" },
      98             :     { "listreceivedbylabel", 1, "include_empty" },
      99             :     { "listreceivedbylabel", 2, "include_watchonly" },
     100             :     { "listreceivedbyshieldaddress", 1, "minconf" },
     101             :     { "listshieldunspent", 0, "minconf" },
     102             :     { "listshieldunspent", 1, "maxconf" },
     103             :     { "listshieldunspent", 2, "include_watchonly" },
     104             :     { "listshieldunspent", 3, "addresses" },
     105             :     { "listsinceblock", 1, "target_confirmations" },
     106             :     { "listsinceblock", 2, "include_watchonly" },
     107             :     { "listtransactions", 1, "count" },
     108             :     { "listtransactions", 2, "from" },
     109             :     { "listtransactions", 3, "include_watchonly" },
     110             :     { "listtransactions", 4, "include_delegated" },
     111             :     { "listtransactions", 5, "include_cold" },
     112             :     { "listunspent", 0, "minconf" },
     113             :     { "listunspent", 1, "maxconf" },
     114             :     { "listunspent", 2, "addresses" },
     115             :     { "listunspent", 3, "watchonly_config" },
     116             :     { "listunspent", 4, "query_options" },
     117             :     { "listunspent", 5, "include_unsafe" },
     118             :     { "lockunspent", 0, "unlock" },
     119             :     { "lockunspent", 1, "transparent" },
     120             :     { "lockunspent", 2, "transactions" },
     121             :     { "logging", 0, "include" },
     122             :     { "logging", 1, "exclude" },
     123             :     { "mnbudgetvote", 4, "legacy" },
     124             :     { "mnbudgetrawvote", 1, "collat_vout" },
     125             :     { "mnbudgetrawvote", 4, "time" },
     126             :     { "preparebudget", 2, "npayments" },
     127             :     { "preparebudget", 3, "start" },
     128             :     { "preparebudget", 5, "montly_payment" },
     129             :     { "prioritisetransaction", 1, "fee_delta" },
     130             :     { "quorumdkgsimerror", 1, "rate" },
     131             :     { "quorumdkgstatus", 0, "detail_level" },
     132             :     { "listquorums", 0, "count" },
     133             :     { "getquoruminfo", 0, "llmqType" },
     134             :     { "getquoruminfo", 2, "includeSkShare" },
     135             :     { "signsession", 0, "llmqType"},
     136             :     { "hasrecoverysignature", 0, "llmqType" },
     137             :     { "issessionconflicting", 0, "llmqType" },
     138             :     { "rawdelegatestake", 1, "amount" },
     139             :     { "rawdelegatestake", 3, "ext_owner" },
     140             :     { "rawdelegatestake", 4, "include_delegated" },
     141             :     { "rawdelegatestake", 5, "from_shield" },
     142             :     { "rawdelegatestake", 6, "force" },
     143             :     { "rawshieldsendmany", 1, "amounts" },
     144             :     { "rawshieldsendmany", 2, "minconf" },
     145             :     { "rawshieldsendmany", 3, "fee" },
     146             :     { "rescanblockchain", 0, "start_height"},
     147             :     { "rescanblockchain", 1, "stop_height"},
     148             :     { "sendmany", 1, "amounts" },
     149             :     { "sendmany", 2, "minconf" },
     150             :     { "sendmany", 4, "include_delegated" },
     151             :     { "sendmany", 5, "subtract_fee_from" },
     152             :     { "scantxoutset", 1, "scanobjects" },
     153             :     { "sendrawtransaction", 1, "allowhighfees" },
     154             :     { "sendtoaddress", 1, "amount" },
     155             :     { "sendtoaddress", 4, "subtract_fee" },
     156             :     { "setautocombinethreshold", 0, "enable" },
     157             :     { "setautocombinethreshold", 1, "threshold" },
     158             :     { "setautocombinethreshold", 2, "frequency"},
     159             :     { "setnetworkactive", 0, "active" },
     160             :     { "setban", 2, "bantime" },
     161             :     { "setban", 3, "absolute" },
     162             :     { "setgenerate", 0, "generate" },
     163             :     { "setgenerate", 1, "genproclimit" },
     164             :     { "sethdseed", 0, "newkeypool" },
     165             :     { "setmocktime", 0, "timestamp" },
     166             :     { "setstakesplitthreshold", 0, "value" },
     167             :     { "settxfee", 0, "amount" },
     168             :     { "shieldsendmany", 1, "amounts" },
     169             :     { "shieldsendmany", 2, "minconf" },
     170             :     { "shieldsendmany", 3, "fee" },
     171             :     { "shieldsendmany", 4, "subtract_fee_from" },
     172             :     { "signrawtransaction", 1, "prevtxs" },
     173             :     { "signrawtransaction", 2, "privkeys" },
     174             :     { "spork", 1, "value" },
     175             :     { "startmasternode", 1, "lock_wallet" },
     176             :     { "startmasternode", 3, "reload_conf" },
     177             :     { "stop", 0, "wait" },
     178             :     { "submitbudget", 2, "npayments" },
     179             :     { "submitbudget", 3, "start" },
     180             :     { "submitbudget", 5, "montly_payment" },
     181             :     { "verifychain", 0, "nblocks" },
     182             :     { "waitforblock", 1, "timeout" },
     183             :     { "waitforblockheight", 0, "height" },
     184             :     { "waitforblockheight", 1, "timeout" },
     185             :     { "waitfornewblock", 0, "timeout" },
     186             :     { "walletpassphrase", 1, "timeout" },
     187             :     { "walletpassphrase", 2, "staking_only" },
     188             :     { "mnconnect", 1, "mn_list" },
     189             :     { "mnconnect", 2, "llmq_type" },
     190             :     // Echo with conversion (For testing only)
     191             :     { "echojson", 0, "arg0" },
     192             :     { "echojson", 1, "arg1" },
     193             :     { "echojson", 2, "arg2" },
     194             :     { "echojson", 3, "arg3" },
     195             :     { "echojson", 4, "arg4" },
     196             :     { "echojson", 5, "arg5" },
     197             :     { "echojson", 6, "arg6" },
     198             :     { "echojson", 7, "arg7" },
     199             :     { "echojson", 8, "arg8" },
     200             :     { "echojson", 9, "arg9" },
     201             : };
     202             : // clang-format on
     203             : 
     204             : class CRPCConvertTable
     205             : {
     206             : private:
     207             :     std::set<std::pair<std::string, int>> members;
     208             :     std::set<std::pair<std::string, std::string>> membersByName;
     209             : 
     210             : public:
     211             :     CRPCConvertTable();
     212             : 
     213        2178 :     bool convert(const std::string& method, int idx)
     214             :     {
     215        4356 :         return (members.count(std::make_pair(method, idx)) > 0);
     216             :     }
     217           0 :     bool convert(const std::string& method, const std::string& name)
     218             :     {
     219           0 :         return (membersByName.count(std::make_pair(method, name)) > 0);
     220             :     }
     221             : };
     222             : 
     223          91 : CRPCConvertTable::CRPCConvertTable()
     224             : {
     225          91 :     const unsigned int n_elem =
     226             :         (sizeof(vRPCConvertParams) / sizeof(vRPCConvertParams[0]));
     227             : 
     228       15561 :     for (unsigned int i = 0; i < n_elem; i++) {
     229       15470 :         members.insert(std::make_pair(vRPCConvertParams[i].methodName,
     230       30940 :                                       vRPCConvertParams[i].paramIdx));
     231       30940 :         membersByName.insert(std::make_pair(vRPCConvertParams[i].methodName,
     232       30940 :                                             vRPCConvertParams[i].paramName));
     233             :     }
     234          91 : }
     235             : 
     236             : static CRPCConvertTable rpcCvtTable;
     237             : 
     238             : /** Non-RFC4627 JSON parser, accepts internal values (such as numbers, true, false, null)
     239             :  * as well as objects and arrays.
     240             :  */
     241         101 : UniValue ParseNonRFCJSONValue(const std::string& strVal)
     242             : {
     243         177 :     UniValue jVal;
     244         227 :     if (!jVal.read(std::string("[")+strVal+std::string("]")) ||
     245         202 :         !jVal.isArray() || jVal.size()!=1)
     246          50 :         throw std::runtime_error(std::string("Error parsing JSON:")+strVal);
     247         152 :     return jVal[0];
     248             : }
     249             : 
     250        2120 : UniValue RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams)
     251             : {
     252        2120 :     UniValue params(UniValue::VARR);
     253             : 
     254        4279 :     for (unsigned int idx = 0; idx < strParams.size(); idx++) {
     255        2178 :         const std::string& strVal = strParams[idx];
     256             : 
     257        2178 :         if (!rpcCvtTable.convert(strMethod, idx)) {
     258             :             // insert string value directly
     259        2086 :             params.push_back(strVal);
     260             :         } else {
     261             :             // parse string as JSON, insert bool/number/object/etc. value
     262          92 :             params.push_back(ParseNonRFCJSONValue(strVal));
     263             :         }
     264             :     }
     265             : 
     266        2101 :     return params;
     267             : }
     268             : 
     269           0 : UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector<std::string> &strParams)
     270             : {
     271           0 :     UniValue params(UniValue::VOBJ);
     272             : 
     273           0 :     for (const std::string &s: strParams) {
     274           0 :         size_t pos = s.find('=');
     275           0 :         if (pos == std::string::npos) {
     276           0 :             throw(std::runtime_error("No '=' in named argument '"+s+"', this needs to be present for every argument (even if it is empty)"));
     277             :         }
     278             : 
     279           0 :         std::string name = s.substr(0, pos);
     280           0 :         std::string value = s.substr(pos+1);
     281             : 
     282           0 :         if (!rpcCvtTable.convert(strMethod, name)) {
     283             :             // insert string value directly
     284           0 :             params.pushKV(name, value);
     285             :         } else {
     286             :             // parse string as JSON, insert bool/number/object/etc. value
     287           0 :             params.pushKV(name, ParseNonRFCJSONValue(value));
     288             :         }
     289             :     }
     290             : 
     291           0 :     return params;
     292             : }

Generated by: LCOV version 1.14