@@ -20,111 +20,130 @@ class CRPCConvertParam
2020public:
2121 std::string methodName; // !< method whose params want conversion
2222 int paramIdx; // !< 0-based idx of param to convert
23+ std::string paramName; // !< parameter name
2324};
2425
26+ /* *
27+ * Specifiy a (method, idx, name) here if the argument is a non-string RPC
28+ * argument and needs to be converted from JSON.
29+ *
30+ * @note Parameter indexes start from 0.
31+ */
2532static const CRPCConvertParam vRPCConvertParams[] =
2633{
27- { " stop" , 0 },
28- { " setmocktime" , 0 },
29- { " generate" , 0 },
30- { " generate" , 1 },
31- { " generatetoaddress" , 0 },
32- { " generatetoaddress" , 2 },
33- { " getnetworkhashps" , 0 },
34- { " getnetworkhashps" , 1 },
35- { " sendtoaddress" , 1 },
36- { " sendtoaddress" , 4 },
37- { " settxfee" , 0 },
38- { " getreceivedbyaddress" , 1 },
39- { " getreceivedbyaccount" , 1 },
40- { " listreceivedbyaddress" , 0 },
41- { " listreceivedbyaddress" , 1 },
42- { " listreceivedbyaddress" , 2 },
43- { " listreceivedbyaccount" , 0 },
44- { " listreceivedbyaccount" , 1 },
45- { " listreceivedbyaccount" , 2 },
46- { " getbalance" , 1 },
47- { " getbalance" , 2 },
48- { " getblockhash" , 0 },
49- { " waitforblockheight" , 0 },
50- { " waitforblockheight" , 1 },
51- { " waitforblock" , 1 },
52- { " waitforblock" , 2 },
53- { " waitfornewblock" , 0 },
54- { " waitfornewblock" , 1 },
55- { " move" , 2 },
56- { " move" , 3 },
57- { " sendfrom" , 2 },
58- { " sendfrom" , 3 },
59- { " listtransactions" , 1 },
60- { " listtransactions" , 2 },
61- { " listtransactions" , 3 },
62- { " listaccounts" , 0 },
63- { " listaccounts" , 1 },
64- { " walletpassphrase" , 1 },
65- { " getblocktemplate" , 0 },
66- { " listsinceblock" , 1 },
67- { " listsinceblock" , 2 },
68- { " sendmany" , 1 },
69- { " sendmany" , 2 },
70- { " sendmany" , 4 },
71- { " addmultisigaddress" , 0 },
72- { " addmultisigaddress" , 1 },
73- { " createmultisig" , 0 },
74- { " createmultisig" , 1 },
75- { " listunspent" , 0 },
76- { " listunspent" , 1 },
77- { " listunspent" , 2 },
78- { " getblock" , 1 },
79- { " getblockheader" , 1 },
80- { " gettransaction" , 1 },
81- { " getrawtransaction" , 1 },
82- { " createrawtransaction" , 0 },
83- { " createrawtransaction" , 1 },
84- { " createrawtransaction" , 2 },
85- { " signrawtransaction" , 1 },
86- { " signrawtransaction" , 2 },
87- { " sendrawtransaction" , 1 },
88- { " fundrawtransaction" , 1 },
89- { " gettxout" , 1 },
90- { " gettxout" , 2 },
91- { " gettxoutproof" , 0 },
92- { " lockunspent" , 0 },
93- { " lockunspent" , 1 },
94- { " importprivkey" , 2 },
95- { " importaddress" , 2 },
96- { " importaddress" , 3 },
97- { " importpubkey" , 2 },
98- { " importmulti" , 0 },
99- { " importmulti" , 1 },
100- { " verifychain" , 0 },
101- { " verifychain" , 1 },
102- { " keypoolrefill" , 0 },
103- { " getrawmempool" , 0 },
104- { " estimatefee" , 0 },
105- { " estimatepriority" , 0 },
106- { " estimatesmartfee" , 0 },
107- { " estimatesmartpriority" , 0 },
108- { " prioritisetransaction" , 1 },
109- { " prioritisetransaction" , 2 },
110- { " setban" , 2 },
111- { " setban" , 3 },
112- { " setnetworkactive" , 0 },
113- { " getmempoolancestors" , 1 },
114- { " getmempooldescendants" , 1 },
34+ { " setmocktime" , 0 , " timestamp" },
35+ { " generate" , 0 , " nblocks" },
36+ { " generate" , 1 , " maxtries" },
37+ { " generatetoaddress" , 0 , " nblocks" },
38+ { " generatetoaddress" , 2 , " maxtries" },
39+ { " getnetworkhashps" , 0 , " nblocks" },
40+ { " getnetworkhashps" , 1 , " height" },
41+ { " sendtoaddress" , 1 , " amount" },
42+ { " sendtoaddress" , 4 , " subtractfeefromamount" },
43+ { " settxfee" , 0 , " amount" },
44+ { " getreceivedbyaddress" , 1 , " minconf" },
45+ { " getreceivedbyaccount" , 1 , " minconf" },
46+ { " listreceivedbyaddress" , 0 , " minconf" },
47+ { " listreceivedbyaddress" , 1 , " include_empty" },
48+ { " listreceivedbyaddress" , 2 , " include_watchonly" },
49+ { " listreceivedbyaccount" , 0 , " minconf" },
50+ { " listreceivedbyaccount" , 1 , " include_empty" },
51+ { " listreceivedbyaccount" , 2 , " include_watchonly" },
52+ { " getbalance" , 1 , " minconf" },
53+ { " getbalance" , 2 , " include_watchonly" },
54+ { " getblockhash" , 0 , " index" },
55+ { " waitforblockheight" , 0 , " height" },
56+ { " waitforblockheight" , 1 , " timeout" },
57+ { " waitforblock" , 1 , " timeout" },
58+ { " waitfornewblock" , 0 , " timeout" },
59+ { " move" , 2 , " amount" },
60+ { " move" , 3 , " minconf" },
61+ { " sendfrom" , 2 , " amount" },
62+ { " sendfrom" , 3 , " minconf" },
63+ { " listtransactions" , 1 , " count" },
64+ { " listtransactions" , 2 , " from" },
65+ { " listtransactions" , 3 , " include_watchonly" },
66+ { " listaccounts" , 0 , " minconf" },
67+ { " listaccounts" , 1 , " include_watchonly" },
68+ { " walletpassphrase" , 1 , " timeout" },
69+ { " getblocktemplate" , 0 , " template_request" },
70+ { " listsinceblock" , 1 , " target_confirmations" },
71+ { " listsinceblock" , 2 , " include_watchonly" },
72+ { " sendmany" , 1 , " amounts" },
73+ { " sendmany" , 2 , " minconf" },
74+ { " sendmany" , 4 , " subtractfeefrom" },
75+ { " addmultisigaddress" , 0 , " nrequired" },
76+ { " addmultisigaddress" , 1 , " keys" },
77+ { " createmultisig" , 0 , " nrequired" },
78+ { " createmultisig" , 1 , " keys" },
79+ { " listunspent" , 0 , " minconf" },
80+ { " listunspent" , 1 , " maxconf" },
81+ { " listunspent" , 2 , " addresses" },
82+ { " getblock" , 1 , " verbose" },
83+ { " getblockheader" , 1 , " verbose" },
84+ { " gettransaction" , 1 , " include_watchonly" },
85+ { " getrawtransaction" , 1 , " verbose" },
86+ { " createrawtransaction" , 0 , " transactions" },
87+ { " createrawtransaction" , 1 , " outputs" },
88+ { " createrawtransaction" , 2 , " locktime" },
89+ { " signrawtransaction" , 1 , " prevtxs" },
90+ { " signrawtransaction" , 2 , " privkeys" },
91+ { " sendrawtransaction" , 1 , " allowhighfees" },
92+ { " fundrawtransaction" , 1 , " options" },
93+ { " gettxout" , 1 , " n" },
94+ { " gettxout" , 2 , " include_mempool" },
95+ { " gettxoutproof" , 0 , " txids" },
96+ { " lockunspent" , 0 , " unlock" },
97+ { " lockunspent" , 1 , " transactions" },
98+ { " importprivkey" , 2 , " rescan" },
99+ { " importaddress" , 2 , " rescan" },
100+ { " importaddress" , 3 , " p2sh" },
101+ { " importpubkey" , 2 , " rescan" },
102+ { " importmulti" , 0 , " requests" },
103+ { " importmulti" , 1 , " options" },
104+ { " verifychain" , 0 , " checklevel" },
105+ { " verifychain" , 1 , " nblocks" },
106+ { " keypoolrefill" , 0 , " newsize" },
107+ { " getrawmempool" , 0 , " verbose" },
108+ { " estimatefee" , 0 , " nblocks" },
109+ { " estimatepriority" , 0 , " nblocks" },
110+ { " estimatesmartfee" , 0 , " nblocks" },
111+ { " estimatesmartpriority" , 0 , " nblocks" },
112+ { " prioritisetransaction" , 1 , " priority_delta" },
113+ { " prioritisetransaction" , 2 , " fee_delta" },
114+ { " setban" , 2 , " bantime" },
115+ { " setban" , 3 , " absolute" },
116+ { " setnetworkactive" , 0 , " state" },
117+ { " getmempoolancestors" , 1 , " verbose" },
118+ { " getmempooldescendants" , 1 , " verbose" },
119+ // Echo with conversion (For testing only)
120+ { " echojson" , 0 , " arg0" },
121+ { " echojson" , 1 , " arg1" },
122+ { " echojson" , 2 , " arg2" },
123+ { " echojson" , 3 , " arg3" },
124+ { " echojson" , 4 , " arg4" },
125+ { " echojson" , 5 , " arg5" },
126+ { " echojson" , 6 , " arg6" },
127+ { " echojson" , 7 , " arg7" },
128+ { " echojson" , 8 , " arg8" },
129+ { " echojson" , 9 , " arg9" },
115130};
116131
117132class CRPCConvertTable
118133{
119134private:
120- std::set<std::pair<std::string, int > > members;
135+ std::set<std::pair<std::string, int >> members;
136+ std::set<std::pair<std::string, std::string>> membersByName;
121137
122138public:
123139 CRPCConvertTable ();
124140
125141 bool convert (const std::string& method, int idx) {
126142 return (members.count (std::make_pair (method, idx)) > 0 );
127143 }
144+ bool convert (const std::string& method, const std::string& name) {
145+ return (membersByName.count (std::make_pair (method, name)) > 0 );
146+ }
128147};
129148
130149CRPCConvertTable::CRPCConvertTable ()
@@ -135,6 +154,8 @@ CRPCConvertTable::CRPCConvertTable()
135154 for (unsigned int i = 0 ; i < n_elem; i++) {
136155 members.insert (std::make_pair (vRPCConvertParams[i].methodName ,
137156 vRPCConvertParams[i].paramIdx ));
157+ membersByName.insert (std::make_pair (vRPCConvertParams[i].methodName ,
158+ vRPCConvertParams[i].paramName ));
138159 }
139160}
140161
@@ -152,7 +173,6 @@ UniValue ParseNonRFCJSONValue(const std::string& strVal)
152173 return jVal[0 ];
153174}
154175
155- /* * Convert strings to command-specific RPC representation */
156176UniValue RPCConvertValues (const std::string &strMethod, const std::vector<std::string> &strParams)
157177{
158178 UniValue params (UniValue::VARR);
@@ -171,3 +191,28 @@ UniValue RPCConvertValues(const std::string &strMethod, const std::vector<std::s
171191
172192 return params;
173193}
194+
195+ UniValue RPCConvertNamedValues (const std::string &strMethod, const std::vector<std::string> &strParams)
196+ {
197+ UniValue params (UniValue::VOBJ);
198+
199+ for (const std::string &s: strParams) {
200+ size_t pos = s.find (" =" );
201+ if (pos == std::string::npos) {
202+ throw (std::runtime_error (" No '=' in named argument '" +s+" ', this needs to be present for every argument (even if it is empty)" ));
203+ }
204+
205+ std::string name = s.substr (0 , pos);
206+ std::string value = s.substr (pos+1 );
207+
208+ if (!rpcCvtTable.convert (strMethod, name)) {
209+ // insert string value directly
210+ params.pushKV (name, value);
211+ } else {
212+ // parse string as JSON, insert bool/number/object/etc. value
213+ params.pushKV (name, ParseNonRFCJSONValue (value));
214+ }
215+ }
216+
217+ return params;
218+ }
0 commit comments