Bitcoin Core  24.99.0
P2P Digital Currency
client.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <rpc/client.h>
7 #include <util/system.h>
8 
9 #include <set>
10 #include <stdint.h>
11 
13 {
14 public:
15  std::string methodName;
16  int paramIdx;
17  std::string paramName;
18 };
19 
20 // clang-format off
28 {
29  { "setmocktime", 0, "timestamp" },
30  { "mockscheduler", 0, "delta_time" },
31  { "utxoupdatepsbt", 1, "descriptors" },
32  { "generatetoaddress", 0, "nblocks" },
33  { "generatetoaddress", 2, "maxtries" },
34  { "generatetodescriptor", 0, "num_blocks" },
35  { "generatetodescriptor", 2, "maxtries" },
36  { "generateblock", 1, "transactions" },
37  { "getnetworkhashps", 0, "nblocks" },
38  { "getnetworkhashps", 1, "height" },
39  { "sendtoaddress", 1, "amount" },
40  { "sendtoaddress", 4, "subtractfeefromamount" },
41  { "sendtoaddress", 5 , "replaceable" },
42  { "sendtoaddress", 6 , "conf_target" },
43  { "sendtoaddress", 8, "avoid_reuse" },
44  { "sendtoaddress", 9, "fee_rate"},
45  { "sendtoaddress", 10, "verbose"},
46  { "settxfee", 0, "amount" },
47  { "sethdseed", 0, "newkeypool" },
48  { "getreceivedbyaddress", 1, "minconf" },
49  { "getreceivedbyaddress", 2, "include_immature_coinbase" },
50  { "getreceivedbylabel", 1, "minconf" },
51  { "getreceivedbylabel", 2, "include_immature_coinbase" },
52  { "listreceivedbyaddress", 0, "minconf" },
53  { "listreceivedbyaddress", 1, "include_empty" },
54  { "listreceivedbyaddress", 2, "include_watchonly" },
55  { "listreceivedbyaddress", 4, "include_immature_coinbase" },
56  { "listreceivedbylabel", 0, "minconf" },
57  { "listreceivedbylabel", 1, "include_empty" },
58  { "listreceivedbylabel", 2, "include_watchonly" },
59  { "listreceivedbylabel", 3, "include_immature_coinbase" },
60  { "getbalance", 1, "minconf" },
61  { "getbalance", 2, "include_watchonly" },
62  { "getbalance", 3, "avoid_reuse" },
63  { "getblockfrompeer", 1, "peer_id" },
64  { "getblockhash", 0, "height" },
65  { "waitforblockheight", 0, "height" },
66  { "waitforblockheight", 1, "timeout" },
67  { "waitforblock", 1, "timeout" },
68  { "waitfornewblock", 0, "timeout" },
69  { "listtransactions", 1, "count" },
70  { "listtransactions", 2, "skip" },
71  { "listtransactions", 3, "include_watchonly" },
72  { "walletpassphrase", 1, "timeout" },
73  { "getblocktemplate", 0, "template_request" },
74  { "listsinceblock", 1, "target_confirmations" },
75  { "listsinceblock", 2, "include_watchonly" },
76  { "listsinceblock", 3, "include_removed" },
77  { "listsinceblock", 4, "include_change" },
78  { "sendmany", 1, "amounts" },
79  { "sendmany", 2, "minconf" },
80  { "sendmany", 4, "subtractfeefrom" },
81  { "sendmany", 5 , "replaceable" },
82  { "sendmany", 6 , "conf_target" },
83  { "sendmany", 8, "fee_rate"},
84  { "sendmany", 9, "verbose" },
85  { "deriveaddresses", 1, "range" },
86  { "scanblocks", 1, "scanobjects" },
87  { "scanblocks", 2, "start_height" },
88  { "scanblocks", 3, "stop_height" },
89  { "scanblocks", 5, "options" },
90  { "scantxoutset", 1, "scanobjects" },
91  { "addmultisigaddress", 0, "nrequired" },
92  { "addmultisigaddress", 1, "keys" },
93  { "createmultisig", 0, "nrequired" },
94  { "createmultisig", 1, "keys" },
95  { "listunspent", 0, "minconf" },
96  { "listunspent", 1, "maxconf" },
97  { "listunspent", 2, "addresses" },
98  { "listunspent", 3, "include_unsafe" },
99  { "listunspent", 4, "query_options" },
100  { "getblock", 1, "verbosity" },
101  { "getblock", 1, "verbose" },
102  { "getblockheader", 1, "verbose" },
103  { "getchaintxstats", 0, "nblocks" },
104  { "gettransaction", 1, "include_watchonly" },
105  { "gettransaction", 2, "verbose" },
106  { "getrawtransaction", 1, "verbosity" },
107  { "getrawtransaction", 1, "verbose" },
108  { "createrawtransaction", 0, "inputs" },
109  { "createrawtransaction", 1, "outputs" },
110  { "createrawtransaction", 2, "locktime" },
111  { "createrawtransaction", 3, "replaceable" },
112  { "decoderawtransaction", 1, "iswitness" },
113  { "signrawtransactionwithkey", 1, "privkeys" },
114  { "signrawtransactionwithkey", 2, "prevtxs" },
115  { "signrawtransactionwithwallet", 1, "prevtxs" },
116  { "sendrawtransaction", 1, "maxfeerate" },
117  { "testmempoolaccept", 0, "rawtxs" },
118  { "testmempoolaccept", 1, "maxfeerate" },
119  { "submitpackage", 0, "package" },
120  { "combinerawtransaction", 0, "txs" },
121  { "fundrawtransaction", 1, "options" },
122  { "fundrawtransaction", 2, "iswitness" },
123  { "walletcreatefundedpsbt", 0, "inputs" },
124  { "walletcreatefundedpsbt", 1, "outputs" },
125  { "walletcreatefundedpsbt", 2, "locktime" },
126  { "walletcreatefundedpsbt", 3, "options" },
127  { "walletcreatefundedpsbt", 4, "bip32derivs" },
128  { "walletprocesspsbt", 1, "sign" },
129  { "walletprocesspsbt", 3, "bip32derivs" },
130  { "walletprocesspsbt", 4, "finalize" },
131  { "createpsbt", 0, "inputs" },
132  { "createpsbt", 1, "outputs" },
133  { "createpsbt", 2, "locktime" },
134  { "createpsbt", 3, "replaceable" },
135  { "combinepsbt", 0, "txs"},
136  { "joinpsbts", 0, "txs"},
137  { "finalizepsbt", 1, "extract"},
138  { "converttopsbt", 1, "permitsigdata"},
139  { "converttopsbt", 2, "iswitness"},
140  { "gettxout", 1, "n" },
141  { "gettxout", 2, "include_mempool" },
142  { "gettxoutproof", 0, "txids" },
143  { "gettxoutsetinfo", 1, "hash_or_height" },
144  { "gettxoutsetinfo", 2, "use_index"},
145  { "lockunspent", 0, "unlock" },
146  { "lockunspent", 1, "transactions" },
147  { "lockunspent", 2, "persistent" },
148  { "send", 0, "outputs" },
149  { "send", 1, "conf_target" },
150  { "send", 3, "fee_rate"},
151  { "send", 4, "options" },
152  { "sendall", 0, "recipients" },
153  { "sendall", 1, "conf_target" },
154  { "sendall", 3, "fee_rate"},
155  { "sendall", 4, "options" },
156  { "simulaterawtransaction", 0, "rawtxs" },
157  { "simulaterawtransaction", 1, "options" },
158  { "importprivkey", 2, "rescan" },
159  { "importaddress", 2, "rescan" },
160  { "importaddress", 3, "p2sh" },
161  { "importpubkey", 2, "rescan" },
162  { "importmulti", 0, "requests" },
163  { "importmulti", 1, "options" },
164  { "importdescriptors", 0, "requests" },
165  { "listdescriptors", 0, "private" },
166  { "verifychain", 0, "checklevel" },
167  { "verifychain", 1, "nblocks" },
168  { "getblockstats", 0, "hash_or_height" },
169  { "getblockstats", 1, "stats" },
170  { "pruneblockchain", 0, "height" },
171  { "keypoolrefill", 0, "newsize" },
172  { "getrawmempool", 0, "verbose" },
173  { "getrawmempool", 1, "mempool_sequence" },
174  { "estimatesmartfee", 0, "conf_target" },
175  { "estimaterawfee", 0, "conf_target" },
176  { "estimaterawfee", 1, "threshold" },
177  { "prioritisetransaction", 1, "dummy" },
178  { "prioritisetransaction", 2, "fee_delta" },
179  { "setban", 2, "bantime" },
180  { "setban", 3, "absolute" },
181  { "setnetworkactive", 0, "state" },
182  { "setwalletflag", 1, "value" },
183  { "getmempoolancestors", 1, "verbose" },
184  { "getmempooldescendants", 1, "verbose" },
185  { "gettxspendingprevout", 0, "outputs" },
186  { "bumpfee", 1, "options" },
187  { "psbtbumpfee", 1, "options" },
188  { "logging", 0, "include" },
189  { "logging", 1, "exclude" },
190  { "disconnectnode", 1, "nodeid" },
191  { "upgradewallet", 0, "version" },
192  // Echo with conversion (For testing only)
193  { "echojson", 0, "arg0" },
194  { "echojson", 1, "arg1" },
195  { "echojson", 2, "arg2" },
196  { "echojson", 3, "arg3" },
197  { "echojson", 4, "arg4" },
198  { "echojson", 5, "arg5" },
199  { "echojson", 6, "arg6" },
200  { "echojson", 7, "arg7" },
201  { "echojson", 8, "arg8" },
202  { "echojson", 9, "arg9" },
203  { "rescanblockchain", 0, "start_height"},
204  { "rescanblockchain", 1, "stop_height"},
205  { "createwallet", 1, "disable_private_keys"},
206  { "createwallet", 2, "blank"},
207  { "createwallet", 4, "avoid_reuse"},
208  { "createwallet", 5, "descriptors"},
209  { "createwallet", 6, "load_on_startup"},
210  { "createwallet", 7, "external_signer"},
211  { "restorewallet", 2, "load_on_startup"},
212  { "loadwallet", 1, "load_on_startup"},
213  { "unloadwallet", 1, "load_on_startup"},
214  { "getnodeaddresses", 0, "count"},
215  { "addpeeraddress", 1, "port"},
216  { "addpeeraddress", 2, "tried"},
217  { "stop", 0, "wait" },
218 };
219 // clang-format on
220 
222 {
223 private:
224  std::set<std::pair<std::string, int>> members;
225  std::set<std::pair<std::string, std::string>> membersByName;
226 
227 public:
229 
231  UniValue ArgToUniValue(const std::string& arg_value, const std::string& method, int param_idx)
232  {
233  return members.count(std::make_pair(method, param_idx)) > 0 ? ParseNonRFCJSONValue(arg_value) : arg_value;
234  }
235 
237  UniValue ArgToUniValue(const std::string& arg_value, const std::string& method, const std::string& param_name)
238  {
239  return membersByName.count(std::make_pair(method, param_name)) > 0 ? ParseNonRFCJSONValue(arg_value) : arg_value;
240  }
241 };
242 
244 {
245  for (const auto& cp : vRPCConvertParams) {
246  members.emplace(cp.methodName, cp.paramIdx);
247  membersByName.emplace(cp.methodName, cp.paramName);
248  }
249 }
250 
252 
256 UniValue ParseNonRFCJSONValue(const std::string& strVal)
257 {
258  UniValue jVal;
259  if (!jVal.read(std::string("[")+strVal+std::string("]")) ||
260  !jVal.isArray() || jVal.size()!=1)
261  throw std::runtime_error(std::string("Error parsing JSON: ") + strVal);
262  return jVal[0];
263 }
264 
265 UniValue RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams)
266 {
267  UniValue params(UniValue::VARR);
268 
269  for (unsigned int idx = 0; idx < strParams.size(); idx++) {
270  const std::string& strVal = strParams[idx];
271  params.push_back(rpcCvtTable.ArgToUniValue(strVal, strMethod, idx));
272  }
273 
274  return params;
275 }
276 
277 UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector<std::string> &strParams)
278 {
279  UniValue params(UniValue::VOBJ);
280  UniValue positional_args{UniValue::VARR};
281 
282  for (const std::string &s: strParams) {
283  size_t pos = s.find('=');
284  if (pos == std::string::npos) {
285  positional_args.push_back(rpcCvtTable.ArgToUniValue(s, strMethod, positional_args.size()));
286  continue;
287  }
288 
289  std::string name = s.substr(0, pos);
290  std::string value = s.substr(pos+1);
291 
292  // Intentionally overwrite earlier named values with later ones as a
293  // convenience for scripts and command line users that want to merge
294  // options.
295  params.pushKV(name, rpcCvtTable.ArgToUniValue(value, strMethod, name));
296  }
297 
298  if (!positional_args.empty()) {
299  // Use __pushKV instead of pushKV to avoid overwriting an explicit
300  // "args" value with an implicit one. Let the RPC server handle the
301  // request as given.
302  params.__pushKV("args", positional_args);
303  }
304 
305  return params;
306 }
std::string methodName
method whose params want conversion
Definition: client.cpp:15
int paramIdx
0-based idx of param to convert
Definition: client.cpp:16
std::string paramName
parameter name
Definition: client.cpp:17
UniValue ArgToUniValue(const std::string &arg_value, const std::string &method, int param_idx)
Return arg_value as UniValue, and first parse it if it is a non-string parameter.
Definition: client.cpp:231
UniValue ArgToUniValue(const std::string &arg_value, const std::string &method, const std::string &param_name)
Return arg_value as UniValue, and first parse it if it is a non-string parameter.
Definition: client.cpp:237
std::set< std::pair< std::string, std::string > > membersByName
Definition: client.cpp:225
std::set< std::pair< std::string, int > > members
Definition: client.cpp:224
void push_back(UniValue val)
Definition: univalue.cpp:104
bool isArray() const
Definition: univalue.h:81
@ VOBJ
Definition: univalue.h:20
@ VARR
Definition: univalue.h:20
void __pushKV(std::string key, UniValue val)
Definition: univalue.cpp:118
size_t size() const
Definition: univalue.h:67
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:126
bool read(const char *raw, size_t len)
UniValue ParseNonRFCJSONValue(const std::string &strVal)
Non-RFC4627 JSON parser, accepts internal values (such as numbers, true, false, null) as well as obje...
Definition: client.cpp:256
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert positional arguments to command-specific RPC representation.
Definition: client.cpp:265
UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert named arguments to command-specific RPC representation.
Definition: client.cpp:277
static CRPCConvertTable rpcCvtTable
Definition: client.cpp:251
static const CRPCConvertParam vRPCConvertParams[]
Specify a (method, idx, name) here if the argument is a non-string RPC argument and needs to be conve...
Definition: client.cpp:27
const char * name
Definition: rest.cpp:46