rippled
Loading...
Searching...
No Matches
RPCCall.cpp
1#include <xrpld/rpc/RPCCall.h>
2#include <xrpld/rpc/ServerHandler.h>
3
4#include <xrpl/basics/ByteUtilities.h>
5#include <xrpl/basics/Log.h>
6#include <xrpl/basics/StringUtilities.h>
7#include <xrpl/basics/base64.h>
8#include <xrpl/basics/contract.h>
9#include <xrpl/beast/core/LexicalCast.h>
10#include <xrpl/json/json_forwards.h>
11#include <xrpl/json/json_reader.h>
12#include <xrpl/json/to_string.h>
13#include <xrpl/net/HTTPClient.h>
14#include <xrpl/protocol/ApiVersion.h>
15#include <xrpl/protocol/ErrorCodes.h>
16#include <xrpl/protocol/PublicKey.h>
17#include <xrpl/protocol/RPCErr.h>
18#include <xrpl/protocol/SystemParameters.h>
19#include <xrpl/protocol/UintTypes.h>
20#include <xrpl/protocol/jss.h>
21
22#include <boost/algorithm/string/predicate.hpp>
23#include <boost/asio/streambuf.hpp>
24#include <boost/regex.hpp>
25
26#include <array>
27#include <iostream>
28#include <type_traits>
29#include <unordered_map>
30
31namespace ripple {
32
33class RPCParser;
34
35//
36// HTTP protocol
37//
38// This ain't Apache. We're just using HTTP header for the length field
39// and to be compatible with other JSON-RPC implementations.
40//
41
44 std::string const& strHost,
45 std::string const& strPath,
46 std::string const& strMsg,
47 std::unordered_map<std::string, std::string> const& mapRequestHeaders)
48{
50
51 // CHECKME this uses a different version than the replies below use. Is
52 // this by design or an accident or should it be using
53 // BuildInfo::getFullVersionString () as well?
54
55 s << "POST " << (strPath.empty() ? "/" : strPath) << " HTTP/1.0\r\n"
56 << "User-Agent: " << systemName() << "-json-rpc/v1\r\n"
57 << "Host: " << strHost << "\r\n"
58 << "Content-Type: application/json\r\n"
59 << "Content-Length: " << strMsg.size() << "\r\n"
60 << "Accept: application/json\r\n";
61
62 for (auto const& [k, v] : mapRequestHeaders)
63 s << k << ": " << v << "\r\n";
64
65 s << "\r\n" << strMsg;
66
67 return s.str();
68}
69
71{
72private:
73 unsigned const apiVersion_;
75
76 // TODO New routine for parsing ledger parameters, other routines should
77 // standardize on this.
78 static bool
79 jvParseLedger(Json::Value& jvRequest, std::string const& strLedger)
80 {
81 if (strLedger == "current" || strLedger == "closed" ||
82 strLedger == "validated")
83 {
84 jvRequest[jss::ledger_index] = strLedger;
85 }
86 else if (strLedger.length() == 64)
87 {
88 // YYY Could confirm this is a uint256.
89 jvRequest[jss::ledger_hash] = strLedger;
90 }
91 else
92 {
93 jvRequest[jss::ledger_index] =
94 beast::lexicalCast<std::uint32_t>(strLedger);
95 }
96
97 return true;
98 }
99
100 // Build a object { "currency" : "XYZ", "issuer" : "rXYX" }
101 static Json::Value
102 jvParseCurrencyIssuer(std::string const& strCurrencyIssuer)
103 {
104 // Matches a sequence of 3 characters from
105 // `ripple::detail::isoCharSet` (the currency),
106 // optionally followed by a forward slash and some other characters
107 // (the issuer).
108 // https://www.boost.org/doc/libs/1_82_0/libs/regex/doc/html/boost_regex/syntax/perl_syntax.html
109 static boost::regex reCurIss(
110 "\\`([][:alnum:]<>(){}[|?!@#$%^&*]{3})(?:/(.+))?\\'");
111
112 boost::smatch smMatch;
113
114 if (boost::regex_match(strCurrencyIssuer, smMatch, reCurIss))
115 {
117 std::string strCurrency = smMatch[1];
118 std::string strIssuer = smMatch[2];
119
120 jvResult[jss::currency] = strCurrency;
121
122 if (strIssuer.length())
123 {
124 // Could confirm issuer is a valid Ripple address.
125 jvResult[jss::issuer] = strIssuer;
126 }
127
128 return jvResult;
129 }
130 else
131 {
133 std::string("Invalid currency/issuer '") + strCurrencyIssuer +
134 "'");
135 }
136 }
137
138 static bool
140 std::string const& strPk,
142 {
143 if (parseBase58<ripple::PublicKey>(type, strPk))
144 return true;
145
146 auto pkHex = strUnHex(strPk);
147 if (!pkHex)
148 return false;
149
150 if (!publicKeyType(makeSlice(*pkHex)))
151 return false;
152
153 return true;
154 }
155
156private:
158 Json::Value (RPCParser::*)(Json::Value const& jvParams);
159
161 parseAsIs(Json::Value const& jvParams)
162 {
164
165 if (jvParams.isArray() && (jvParams.size() > 0))
166 v[jss::params] = jvParams;
167
168 return v;
169 }
170
172 parseInternal(Json::Value const& jvParams)
173 {
175 v[jss::internal_command] = jvParams[0u];
176
178
179 for (unsigned i = 1; i < jvParams.size(); ++i)
180 params.append(jvParams[i]);
181
182 v[jss::params] = params;
183
184 return v;
185 }
186
188 parseManifest(Json::Value const& jvParams)
189 {
190 if (jvParams.size() == 1)
191 {
193
194 std::string const strPk = jvParams[0u].asString();
197
198 jvRequest[jss::public_key] = strPk;
199
200 return jvRequest;
201 }
202
204 }
205
206 // fetch_info [clear]
209 {
211 unsigned int iParams = jvParams.size();
212
213 if (iParams != 0)
214 jvRequest[jvParams[0u].asString()] = true;
215
216 return jvRequest;
217 }
218
219 // account_tx accountID [ledger_min [ledger_max [limit [offset]]]] [binary]
220 // [count] [descending]
223 {
225 unsigned int iParams = jvParams.size();
226
227 auto const account = parseBase58<AccountID>(jvParams[0u].asString());
228 if (!account)
230
231 jvRequest[jss::account] = toBase58(*account);
232
233 bool bDone = false;
234
235 while (!bDone && iParams >= 2)
236 {
237 // VFALCO Why is Json::StaticString appearing on the right side?
238 if (jvParams[iParams - 1].asString() == jss::binary)
239 {
240 jvRequest[jss::binary] = true;
241 --iParams;
242 }
243 else if (jvParams[iParams - 1].asString() == jss::count)
244 {
245 jvRequest[jss::count] = true;
246 --iParams;
247 }
248 else if (jvParams[iParams - 1].asString() == jss::descending)
249 {
250 jvRequest[jss::descending] = true;
251 --iParams;
252 }
253 else
254 {
255 bDone = true;
256 }
257 }
258
259 if (1 == iParams)
260 {
261 }
262 else if (2 == iParams)
263 {
264 if (!jvParseLedger(jvRequest, jvParams[1u].asString()))
265 return jvRequest;
266 }
267 else
268 {
269 std::int64_t uLedgerMin = jvParams[1u].asInt();
270 std::int64_t uLedgerMax = jvParams[2u].asInt();
271
272 if (uLedgerMax != -1 && uLedgerMax < uLedgerMin)
273 {
274 if (apiVersion_ == 1)
276 return rpcError(rpcNOT_SYNCED);
277 }
278
279 jvRequest[jss::ledger_index_min] = jvParams[1u].asInt();
280 jvRequest[jss::ledger_index_max] = jvParams[2u].asInt();
281
282 if (iParams >= 4)
283 jvRequest[jss::limit] = jvParams[3u].asInt();
284
285 if (iParams >= 5)
286 jvRequest[jss::offset] = jvParams[4u].asInt();
287 }
288
289 return jvRequest;
290 }
291
292 // book_offers <taker_pays> <taker_gets> [<taker> [<ledger> [<limit>
293 // [<proof> [<marker>]]]]] limit: 0 = no limit proof: 0 or 1
294 //
295 // Mnemonic: taker pays --> offer --> taker gets
298 {
300
301 Json::Value jvTakerPays =
302 jvParseCurrencyIssuer(jvParams[0u].asString());
303 Json::Value jvTakerGets =
304 jvParseCurrencyIssuer(jvParams[1u].asString());
305
306 if (isRpcError(jvTakerPays))
307 {
308 return jvTakerPays;
309 }
310 else
311 {
312 jvRequest[jss::taker_pays] = jvTakerPays;
313 }
314
315 if (isRpcError(jvTakerGets))
316 {
317 return jvTakerGets;
318 }
319 else
320 {
321 jvRequest[jss::taker_gets] = jvTakerGets;
322 }
323
324 if (jvParams.size() >= 3)
325 {
326 jvRequest[jss::issuer] = jvParams[2u].asString();
327 }
328
329 if (jvParams.size() >= 4 &&
330 !jvParseLedger(jvRequest, jvParams[3u].asString()))
331 return jvRequest;
332
333 if (jvParams.size() >= 5)
334 {
335 try
336 {
337 int iLimit = jvParams[4u].asInt();
338
339 if (iLimit > 0)
340 jvRequest[jss::limit] = iLimit;
341 }
342 catch (std::exception const&)
343 {
344 return RPC::invalid_field_error(jss::limit);
345 }
346 }
347
348 if (jvParams.size() >= 6)
349 {
350 try
351 {
352 int bProof = jvParams[5u].asInt();
353 if (bProof)
354 jvRequest[jss::proof] = true;
355 }
356 catch (std::exception const&)
357 {
358 return RPC::invalid_field_error(jss::proof);
359 }
360 }
361
362 if (jvParams.size() == 7)
363 jvRequest[jss::marker] = jvParams[6u];
364
365 return jvRequest;
366 }
367
368 // can_delete [<ledgerid>|<ledgerhash>|now|always|never]
371 {
373
374 if (!jvParams.size())
375 return jvRequest;
376
377 std::string input = jvParams[0u].asString();
378 if (input.find_first_not_of("0123456789") == std::string::npos)
379 jvRequest["can_delete"] = jvParams[0u].asUInt();
380 else
381 jvRequest["can_delete"] = input;
382
383 return jvRequest;
384 }
385
386 // connect <ip[:port]> [port]
388 parseConnect(Json::Value const& jvParams)
389 {
391 std::string ip = jvParams[0u].asString();
392 if (jvParams.size() == 2)
393 {
394 jvRequest[jss::ip] = ip;
395 jvRequest[jss::port] = jvParams[1u].asUInt();
396 return jvRequest;
397 }
398
399 // handle case where there is one argument of the form ip:port
400 if (std::count(ip.begin(), ip.end(), ':') == 1)
401 {
402 std::size_t colon = ip.find_last_of(":");
403 jvRequest[jss::ip] = std::string{ip, 0, colon};
404 jvRequest[jss::port] =
405 Json::Value{std::string{ip, colon + 1}}.asUInt();
406 return jvRequest;
407 }
408
409 // default case, no port
410 jvRequest[jss::ip] = ip;
411 return jvRequest;
412 }
413
414 // deposit_authorized <source_account> <destination_account>
415 // [<ledger> [<credentials>, ...]]
418 {
420 jvRequest[jss::source_account] = jvParams[0u].asString();
421 jvRequest[jss::destination_account] = jvParams[1u].asString();
422
423 if (jvParams.size() >= 3)
424 jvParseLedger(jvRequest, jvParams[2u].asString());
425
426 // 8 credentials max
427 if ((jvParams.size() >= 4) && (jvParams.size() <= 11))
428 {
429 jvRequest[jss::credentials] = Json::Value(Json::arrayValue);
430 for (uint32_t i = 3; i < jvParams.size(); ++i)
431 jvRequest[jss::credentials].append(jvParams[i].asString());
432 }
433
434 return jvRequest;
435 }
436
437 // Return an error for attemping to subscribe/unsubscribe via RPC.
439 parseEvented(Json::Value const& jvParams)
440 {
441 return rpcError(rpcNO_EVENTS);
442 }
443
444 // feature [<feature>] [accept|reject]
446 parseFeature(Json::Value const& jvParams)
447 {
449
450 if (jvParams.size() > 0)
451 jvRequest[jss::feature] = jvParams[0u].asString();
452
453 if (jvParams.size() > 1)
454 {
455 auto const action = jvParams[1u].asString();
456
457 // This may look reversed, but it's intentional: jss::vetoed
458 // determines whether an amendment is vetoed - so "reject" means
459 // that jss::vetoed is true.
460 if (boost::iequals(action, "reject"))
461 jvRequest[jss::vetoed] = Json::Value(true);
462 else if (boost::iequals(action, "accept"))
463 jvRequest[jss::vetoed] = Json::Value(false);
464 else
466 }
467
468 return jvRequest;
469 }
470
471 // get_counts [<min_count>]
474 {
476
477 if (jvParams.size())
478 jvRequest[jss::min_count] = jvParams[0u].asUInt();
479
480 return jvRequest;
481 }
482
483 // sign_for <account> <secret> <json> offline
484 // sign_for <account> <secret> <json>
486 parseSignFor(Json::Value const& jvParams)
487 {
488 bool const bOffline =
489 4 == jvParams.size() && jvParams[3u].asString() == "offline";
490
491 if (3 == jvParams.size() || bOffline)
492 {
493 Json::Value txJSON;
494 Json::Reader reader;
495 if (reader.parse(jvParams[2u].asString(), txJSON))
496 {
497 // sign_for txJSON.
499
500 jvRequest[jss::account] = jvParams[0u].asString();
501 jvRequest[jss::secret] = jvParams[1u].asString();
502 jvRequest[jss::tx_json] = txJSON;
503
504 if (bOffline)
505 jvRequest[jss::offline] = true;
506
507 return jvRequest;
508 }
509 }
511 }
512
513 // json <command> <json>
515 parseJson(Json::Value const& jvParams)
516 {
517 Json::Reader reader;
518 Json::Value jvRequest;
519
520 JLOG(j_.trace()) << "RPC method: " << jvParams[0u];
521 JLOG(j_.trace()) << "RPC json: " << jvParams[1u];
522
523 if (reader.parse(jvParams[1u].asString(), jvRequest))
524 {
525 if (!jvRequest.isObjectOrNull())
527
528 jvRequest[jss::method] = jvParams[0u];
529
530 return jvRequest;
531 }
532
534 }
535
536 bool
538 {
539 if (jv.isArray())
540 {
541 if (jv.size() == 0)
542 return false;
543 for (auto const& j : jv)
544 {
545 if (!isValidJson2(j))
546 return false;
547 }
548 return true;
549 }
550 if (jv.isObject())
551 {
552 if (jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0" &&
553 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0" &&
554 jv.isMember(jss::id) && jv.isMember(jss::method))
555 {
556 if (jv.isMember(jss::params) &&
557 !(jv[jss::params].isNull() || jv[jss::params].isArray() ||
558 jv[jss::params].isObject()))
559 return false;
560 return true;
561 }
562 }
563 return false;
564 }
565
567 parseJson2(Json::Value const& jvParams)
568 {
569 Json::Reader reader;
570 Json::Value jv;
571 bool valid_parse = reader.parse(jvParams[0u].asString(), jv);
572 if (valid_parse && isValidJson2(jv))
573 {
574 if (jv.isObject())
575 {
577 if (jv.isMember(jss::params))
578 {
579 auto const& params = jv[jss::params];
580 for (auto i = params.begin(); i != params.end(); ++i)
581 jv1[i.key().asString()] = *i;
582 }
583 jv1[jss::jsonrpc] = jv[jss::jsonrpc];
584 jv1[jss::ripplerpc] = jv[jss::ripplerpc];
585 jv1[jss::id] = jv[jss::id];
586 jv1[jss::method] = jv[jss::method];
587 return jv1;
588 }
589 // else jv.isArray()
591 for (Json::UInt j = 0; j < jv.size(); ++j)
592 {
593 if (jv[j].isMember(jss::params))
594 {
595 auto const& params = jv[j][jss::params];
596 for (auto i = params.begin(); i != params.end(); ++i)
597 jv1[j][i.key().asString()] = *i;
598 }
599 jv1[j][jss::jsonrpc] = jv[j][jss::jsonrpc];
600 jv1[j][jss::ripplerpc] = jv[j][jss::ripplerpc];
601 jv1[j][jss::id] = jv[j][jss::id];
602 jv1[j][jss::method] = jv[j][jss::method];
603 }
604 return jv1;
605 }
606 auto jv_error = rpcError(rpcINVALID_PARAMS);
607 if (jv.isMember(jss::jsonrpc))
608 jv_error[jss::jsonrpc] = jv[jss::jsonrpc];
609 if (jv.isMember(jss::ripplerpc))
610 jv_error[jss::ripplerpc] = jv[jss::ripplerpc];
611 if (jv.isMember(jss::id))
612 jv_error[jss::id] = jv[jss::id];
613 return jv_error;
614 }
615
616 // ledger [id|index|current|closed|validated] [full|tx]
618 parseLedger(Json::Value const& jvParams)
619 {
621
622 if (!jvParams.size())
623 {
624 return jvRequest;
625 }
626
627 jvParseLedger(jvRequest, jvParams[0u].asString());
628
629 if (2 == jvParams.size())
630 {
631 if (jvParams[1u].asString() == "full")
632 {
633 jvRequest[jss::full] = true;
634 }
635 else if (jvParams[1u].asString() == "tx")
636 {
637 jvRequest[jss::transactions] = true;
638 jvRequest[jss::expand] = true;
639 }
640 }
641
642 return jvRequest;
643 }
644
645 // ledger_header <id>|<index>
647 parseLedgerId(Json::Value const& jvParams)
648 {
650
651 std::string strLedger = jvParams[0u].asString();
652
653 if (strLedger.length() == 64)
654 {
655 jvRequest[jss::ledger_hash] = strLedger;
656 }
657 else
658 {
659 jvRequest[jss::ledger_index] =
660 beast::lexicalCast<std::uint32_t>(strLedger);
661 }
662
663 return jvRequest;
664 }
665
666 // ledger_entry [id] [<index>]
669 {
671
672 jvRequest[jss::index] = jvParams[0u].asString();
673
674 if (jvParams.size() == 2 &&
675 !jvParseLedger(jvRequest, jvParams[1u].asString()))
677
678 return jvRequest;
679 }
680
681 // log_level: Get log levels
682 // log_level <severity>: Set master log level to the
683 // specified severity log_level <partition> <severity>: Set specified
684 // partition to specified severity
686 parseLogLevel(Json::Value const& jvParams)
687 {
689
690 if (jvParams.size() == 1)
691 {
692 jvRequest[jss::severity] = jvParams[0u].asString();
693 }
694 else if (jvParams.size() == 2)
695 {
696 jvRequest[jss::partition] = jvParams[0u].asString();
697 jvRequest[jss::severity] = jvParams[1u].asString();
698 }
699
700 return jvRequest;
701 }
702
703 // owner_info <account>
704 // account_info <account> [<ledger>]
705 // account_offers <account> [<ledger>]
708 {
709 return parseAccountRaw1(jvParams);
710 }
711
714 {
715 return parseAccountRaw1(jvParams);
716 }
717
718 // account_lines <account> <account>|"" [<ledger>]
721 {
722 return parseAccountRaw2(jvParams, jss::peer);
723 }
724
725 // account_channels <account> <account>|"" [<ledger>]
728 {
729 return parseAccountRaw2(jvParams, jss::destination_account);
730 }
731
732 // channel_authorize: <private_key> [<key_type>] <channel_id> <drops>
735 {
737
738 unsigned int index = 0;
739
740 if (jvParams.size() == 4)
741 {
742 jvRequest[jss::passphrase] = jvParams[index];
743 index++;
744
745 if (!keyTypeFromString(jvParams[index].asString()))
747 jvRequest[jss::key_type] = jvParams[index];
748 index++;
749 }
750 else
751 {
752 jvRequest[jss::secret] = jvParams[index];
753 index++;
754 }
755
756 {
757 // verify the channel id is a valid 256 bit number
758 uint256 channelId;
759 if (!channelId.parseHex(jvParams[index].asString()))
761 jvRequest[jss::channel_id] = to_string(channelId);
762 index++;
763 }
764
765 if (!jvParams[index].isString() ||
766 !to_uint64(jvParams[index].asString()))
768 jvRequest[jss::amount] = jvParams[index];
769
770 // If additional parameters are appended, be sure to increment index
771 // here
772
773 return jvRequest;
774 }
775
776 // channel_verify <public_key> <channel_id> <drops> <signature>
779 {
780 std::string const strPk = jvParams[0u].asString();
781
782 if (!validPublicKey(strPk))
784
786
787 jvRequest[jss::public_key] = strPk;
788 {
789 // verify the channel id is a valid 256 bit number
790 uint256 channelId;
791 if (!channelId.parseHex(jvParams[1u].asString()))
793 }
794 jvRequest[jss::channel_id] = jvParams[1u].asString();
795
796 if (!jvParams[2u].isString() || !to_uint64(jvParams[2u].asString()))
798 jvRequest[jss::amount] = jvParams[2u];
799
800 jvRequest[jss::signature] = jvParams[3u].asString();
801
802 return jvRequest;
803 }
804
806 parseAccountRaw2(Json::Value const& jvParams, char const* const acc2Field)
807 {
808 std::array<char const* const, 2> accFields{{jss::account, acc2Field}};
809 auto const nParams = jvParams.size();
811 for (auto i = 0; i < nParams; ++i)
812 {
813 std::string strParam = jvParams[i].asString();
814
815 if (i == 1 && strParam.empty())
816 continue;
817
818 // Parameters 0 and 1 are accounts
819 if (i < 2)
820 {
821 if (parseBase58<AccountID>(strParam))
822 {
823 jvRequest[accFields[i]] = std::move(strParam);
824 }
825 else
826 {
828 }
829 }
830 else
831 {
832 if (jvParseLedger(jvRequest, strParam))
833 return jvRequest;
835 }
836 }
837
838 return jvRequest;
839 }
840
841 // TODO: Get index from an alternate syntax: rXYZ:<index>
844 {
845 std::string strIdent = jvParams[0u].asString();
846 unsigned int iCursor = jvParams.size();
847
848 if (!parseBase58<AccountID>(strIdent))
850
851 // Get info on account.
853
854 jvRequest[jss::account] = strIdent;
855
856 if (iCursor == 2 && !jvParseLedger(jvRequest, jvParams[1u].asString()))
858
859 return jvRequest;
860 }
861
863 parseVault(Json::Value const& jvParams)
864 {
865 std::string strVaultID = jvParams[0u].asString();
866 uint256 id = beast::zero;
867 if (!id.parseHex(strVaultID))
869
871 jvRequest[jss::vault_id] = strVaultID;
872
873 if (jvParams.size() > 1)
874 jvParseLedger(jvRequest, jvParams[1u].asString());
875
876 return jvRequest;
877 }
878
879 // peer_reservations_add <public_key> [<name>]
882 {
883 Json::Value jvRequest;
884 jvRequest[jss::public_key] = jvParams[0u].asString();
885 if (jvParams.size() > 1)
886 {
887 jvRequest[jss::description] = jvParams[1u].asString();
888 }
889 return jvRequest;
890 }
891
892 // peer_reservations_del <public_key>
895 {
896 Json::Value jvRequest;
897 jvRequest[jss::public_key] = jvParams[0u].asString();
898 return jvRequest;
899 }
900
901 // ripple_path_find <json> [<ledger>]
904 {
905 Json::Reader reader;
907 bool bLedger = 2 == jvParams.size();
908
909 JLOG(j_.trace()) << "RPC json: " << jvParams[0u];
910
911 if (reader.parse(jvParams[0u].asString(), jvRequest))
912 {
913 if (bLedger)
914 {
915 jvParseLedger(jvRequest, jvParams[1u].asString());
916 }
917
918 return jvRequest;
919 }
920
922 }
923
924 // simulate any transaction on the network
925 //
926 // simulate <tx_blob> [binary]
927 // simulate <tx_json> [binary]
929 parseSimulate(Json::Value const& jvParams)
930 {
931 Json::Value txJSON;
932 Json::Reader reader;
934
935 if (reader.parse(jvParams[0u].asString(), txJSON))
936 {
937 jvRequest[jss::tx_json] = txJSON;
938 }
939 else
940 {
941 jvRequest[jss::tx_blob] = jvParams[0u].asString();
942 }
943
944 if (jvParams.size() == 2)
945 {
946 if (!jvParams[1u].isString() || jvParams[1u].asString() != "binary")
948 jvRequest[jss::binary] = true;
949 }
950
951 return jvRequest;
952 }
953
954 // sign/submit any transaction to the network
955 //
956 // sign <private_key> <json> offline
957 // submit <private_key> <json>
958 // submit <tx_blob>
961 {
962 Json::Value txJSON;
963 Json::Reader reader;
964 bool const bOffline =
965 jvParams.size() >= 3 && jvParams[2u].asString() == "offline";
966 std::optional<std::string> const field =
967 [&jvParams, bOffline]() -> std::optional<std::string> {
968 if (jvParams.size() < 3)
969 return std::nullopt;
970 if (jvParams.size() < 4 && bOffline)
971 return std::nullopt;
972 Json::UInt index = bOffline ? 3u : 2u;
973 return jvParams[index].asString();
974 }();
975
976 if (1 == jvParams.size())
977 {
978 // Submitting tx_blob
979
981
982 jvRequest[jss::tx_blob] = jvParams[0u].asString();
983
984 return jvRequest;
985 }
986 else if (
987 (jvParams.size() >= 2 || bOffline) &&
988 reader.parse(jvParams[1u].asString(), txJSON))
989 {
990 // Signing or submitting tx_json.
992
993 jvRequest[jss::secret] = jvParams[0u].asString();
994 jvRequest[jss::tx_json] = txJSON;
995
996 if (bOffline)
997 jvRequest[jss::offline] = true;
998
999 if (field)
1000 jvRequest[jss::signature_target] = *field;
1001
1002 return jvRequest;
1003 }
1004
1006 }
1007
1008 // submit any multisigned transaction to the network
1009 //
1010 // submit_multisigned <json>
1013 {
1014 if (1 == jvParams.size())
1015 {
1016 Json::Value txJSON;
1017 Json::Reader reader;
1018 if (reader.parse(jvParams[0u].asString(), txJSON))
1019 {
1020 Json::Value jvRequest{Json::objectValue};
1021 jvRequest[jss::tx_json] = txJSON;
1022 return jvRequest;
1023 }
1024 }
1025
1027 }
1028
1029 // transaction_entry <tx_hash> <ledger_hash/ledger_index>
1032 {
1033 // Parameter count should have already been verified.
1034 XRPL_ASSERT(
1035 jvParams.size() == 2,
1036 "ripple::RPCParser::parseTransactionEntry : valid parameter count");
1037
1038 std::string const txHash = jvParams[0u].asString();
1039 if (txHash.length() != 64)
1041
1042 Json::Value jvRequest{Json::objectValue};
1043 jvRequest[jss::tx_hash] = txHash;
1044
1045 jvParseLedger(jvRequest, jvParams[1u].asString());
1046
1047 // jvParseLedger inserts a "ledger_index" of 0 if it doesn't
1048 // find a match.
1049 if (jvRequest.isMember(jss::ledger_index) &&
1050 jvRequest[jss::ledger_index] == 0)
1052
1053 return jvRequest;
1054 }
1055
1056 // tx <transaction_id>
1058 parseTx(Json::Value const& jvParams)
1059 {
1060 Json::Value jvRequest{Json::objectValue};
1061
1062 if (jvParams.size() == 2 || jvParams.size() == 4)
1063 {
1064 if (jvParams[1u].asString() == jss::binary)
1065 jvRequest[jss::binary] = true;
1066 }
1067
1068 if (jvParams.size() >= 3)
1069 {
1070 auto const offset = jvParams.size() == 3 ? 0 : 1;
1071
1072 jvRequest[jss::min_ledger] = jvParams[1u + offset].asString();
1073 jvRequest[jss::max_ledger] = jvParams[2u + offset].asString();
1074 }
1075
1076 if (jvParams[0u].asString().length() == 16)
1077 jvRequest[jss::ctid] = jvParams[0u].asString();
1078 else
1079 jvRequest[jss::transaction] = jvParams[0u].asString();
1080
1081 return jvRequest;
1082 }
1083
1084 // tx_history <index>
1087 {
1088 Json::Value jvRequest{Json::objectValue};
1089
1090 jvRequest[jss::start] = jvParams[0u].asUInt();
1091
1092 return jvRequest;
1093 }
1094
1095 // validation_create [<pass_phrase>|<seed>|<seed_key>]
1096 //
1097 // NOTE: It is poor security to specify secret information on the command
1098 // line. This information might be saved in the command shell history file
1099 // (e.g. .bash_history) and it may be leaked via the process status command
1100 // (i.e. ps).
1103 {
1104 Json::Value jvRequest{Json::objectValue};
1105
1106 if (jvParams.size())
1107 jvRequest[jss::secret] = jvParams[0u].asString();
1108
1109 return jvRequest;
1110 }
1111
1112 // wallet_propose [<passphrase>]
1113 // <passphrase> is only for testing. Master seeds should only be generated
1114 // randomly.
1117 {
1118 Json::Value jvRequest{Json::objectValue};
1119
1120 if (jvParams.size())
1121 jvRequest[jss::passphrase] = jvParams[0u].asString();
1122
1123 return jvRequest;
1124 }
1125
1126 // parse gateway balances
1127 // gateway_balances [<ledger>] <issuer_account> [ <hotwallet> [ <hotwallet>
1128 // ]]
1129
1132 {
1133 unsigned int index = 0;
1134 unsigned int const size = jvParams.size();
1135
1136 Json::Value jvRequest{Json::objectValue};
1137
1138 std::string param = jvParams[index++].asString();
1139 if (param.empty())
1140 return RPC::make_param_error("Invalid first parameter");
1141
1142 if (param[0] != 'r')
1143 {
1144 if (param.size() == 64)
1145 jvRequest[jss::ledger_hash] = param;
1146 else
1147 jvRequest[jss::ledger_index] = param;
1148
1149 if (size <= index)
1150 return RPC::make_param_error("Invalid hotwallet");
1151
1152 param = jvParams[index++].asString();
1153 }
1154
1155 jvRequest[jss::account] = param;
1156
1157 if (index < size)
1158 {
1159 Json::Value& hotWallets =
1160 (jvRequest["hotwallet"] = Json::arrayValue);
1161 while (index < size)
1162 hotWallets.append(jvParams[index++].asString());
1163 }
1164
1165 return jvRequest;
1166 }
1167
1168 // server_definitions [hash]
1171 {
1172 Json::Value jvRequest{Json::objectValue};
1173
1174 if (jvParams.size() == 1)
1175 {
1176 jvRequest[jss::hash] = jvParams[0u].asString();
1177 }
1178
1179 return jvRequest;
1180 }
1181
1182 // server_info [counters]
1185 {
1186 Json::Value jvRequest(Json::objectValue);
1187 if (jvParams.size() == 1 && jvParams[0u].asString() == "counters")
1188 jvRequest[jss::counters] = true;
1189 return jvRequest;
1190 }
1191
1192public:
1193 //--------------------------------------------------------------------------
1194
1195 explicit RPCParser(unsigned apiVersion, beast::Journal j)
1196 : apiVersion_(apiVersion), j_(j)
1197 {
1198 }
1199
1200 //--------------------------------------------------------------------------
1201
1202 // Convert a rpc method and params to a request.
1203 // <-- { method: xyz, params: [... ] } or { error: ..., ... }
1206 std::string strMethod,
1207 Json::Value jvParams,
1208 bool allowAnyCommand)
1209 {
1210 if (auto stream = j_.trace())
1211 {
1212 stream << "Method: '" << strMethod << "'";
1213 stream << "Params: " << jvParams;
1214 }
1215
1216 struct Command
1217 {
1218 char const* name;
1219 parseFuncPtr parse;
1220 int minParams;
1221 int maxParams;
1222 };
1223
1224 static constexpr Command commands[] = {
1225 // Request-response methods
1226 // - Returns an error, or the request.
1227 // - To modify the method, provide a new method in the request.
1228 {"account_currencies", &RPCParser::parseAccountCurrencies, 1, 3},
1229 {"account_info", &RPCParser::parseAccountItems, 1, 3},
1230 {"account_lines", &RPCParser::parseAccountLines, 1, 5},
1231 {"account_channels", &RPCParser::parseAccountChannels, 1, 3},
1232 {"account_nfts", &RPCParser::parseAccountItems, 1, 5},
1233 {"account_objects", &RPCParser::parseAccountItems, 1, 5},
1234 {"account_offers", &RPCParser::parseAccountItems, 1, 4},
1235 {"account_tx", &RPCParser::parseAccountTransactions, 1, 8},
1236 {"amm_info", &RPCParser::parseAsIs, 1, 2},
1237 {"vault_info", &RPCParser::parseVault, 1, 2},
1238 {"book_changes", &RPCParser::parseLedgerId, 1, 1},
1239 {"book_offers", &RPCParser::parseBookOffers, 2, 7},
1240 {"can_delete", &RPCParser::parseCanDelete, 0, 1},
1241 {"channel_authorize", &RPCParser::parseChannelAuthorize, 3, 4},
1242 {"channel_verify", &RPCParser::parseChannelVerify, 4, 4},
1243 {"connect", &RPCParser::parseConnect, 1, 2},
1244 {"consensus_info", &RPCParser::parseAsIs, 0, 0},
1245 {"deposit_authorized", &RPCParser::parseDepositAuthorized, 2, 11},
1246 {"feature", &RPCParser::parseFeature, 0, 2},
1247 {"fetch_info", &RPCParser::parseFetchInfo, 0, 1},
1248 {"gateway_balances", &RPCParser::parseGatewayBalances, 1, -1},
1249 {"get_counts", &RPCParser::parseGetCounts, 0, 1},
1250 {"json", &RPCParser::parseJson, 2, 2},
1251 {"json2", &RPCParser::parseJson2, 1, 1},
1252 {"ledger", &RPCParser::parseLedger, 0, 2},
1253 {"ledger_accept", &RPCParser::parseAsIs, 0, 0},
1254 {"ledger_closed", &RPCParser::parseAsIs, 0, 0},
1255 {"ledger_current", &RPCParser::parseAsIs, 0, 0},
1256 {"ledger_entry", &RPCParser::parseLedgerEntry, 1, 2},
1257 {"ledger_header", &RPCParser::parseLedgerId, 1, 1},
1258 {"ledger_request", &RPCParser::parseLedgerId, 1, 1},
1259 {"log_level", &RPCParser::parseLogLevel, 0, 2},
1260 {"logrotate", &RPCParser::parseAsIs, 0, 0},
1261 {"manifest", &RPCParser::parseManifest, 1, 1},
1262 {"owner_info", &RPCParser::parseAccountItems, 1, 3},
1263 {"peers", &RPCParser::parseAsIs, 0, 0},
1264 {"ping", &RPCParser::parseAsIs, 0, 0},
1265 {"print", &RPCParser::parseAsIs, 0, 1},
1266 // { "profile", &RPCParser::parseProfile, 1, 9
1267 // },
1268 {"random", &RPCParser::parseAsIs, 0, 0},
1269 {"peer_reservations_add",
1271 1,
1272 2},
1273 {"peer_reservations_del",
1275 1,
1276 1},
1277 {"peer_reservations_list", &RPCParser::parseAsIs, 0, 0},
1278 {"ripple_path_find", &RPCParser::parseRipplePathFind, 1, 2},
1279 {"server_definitions", &RPCParser::parseServerDefinitions, 0, 1},
1280 {"server_info", &RPCParser::parseServerInfo, 0, 1},
1281 {"server_state", &RPCParser::parseServerInfo, 0, 1},
1282 {"sign", &RPCParser::parseSignSubmit, 2, 4},
1283 {"sign_for", &RPCParser::parseSignFor, 3, 4},
1284 {"stop", &RPCParser::parseAsIs, 0, 0},
1285 {"simulate", &RPCParser::parseSimulate, 1, 2},
1286 {"submit", &RPCParser::parseSignSubmit, 1, 4},
1287 {"submit_multisigned", &RPCParser::parseSubmitMultiSigned, 1, 1},
1288 {"transaction_entry", &RPCParser::parseTransactionEntry, 2, 2},
1289 {"tx", &RPCParser::parseTx, 1, 4},
1290 {"tx_history", &RPCParser::parseTxHistory, 1, 1},
1291 {"unl_list", &RPCParser::parseAsIs, 0, 0},
1292 {"validation_create", &RPCParser::parseValidationCreate, 0, 1},
1293 {"validator_info", &RPCParser::parseAsIs, 0, 0},
1294 {"version", &RPCParser::parseAsIs, 0, 0},
1295 {"wallet_propose", &RPCParser::parseWalletPropose, 0, 1},
1296 {"internal", &RPCParser::parseInternal, 1, -1},
1297
1298 // Evented methods
1299 {"path_find", &RPCParser::parseEvented, -1, -1},
1300 {"subscribe", &RPCParser::parseEvented, -1, -1},
1301 {"unsubscribe", &RPCParser::parseEvented, -1, -1},
1302 };
1303
1304 auto const count = jvParams.size();
1305
1306 for (auto const& command : commands)
1307 {
1308 if (strMethod == command.name)
1309 {
1310 if ((command.minParams >= 0 && count < command.minParams) ||
1311 (command.maxParams >= 0 && count > command.maxParams))
1312 {
1313 JLOG(j_.debug())
1314 << "Wrong number of parameters for " << command.name
1315 << " minimum=" << command.minParams
1316 << " maximum=" << command.maxParams
1317 << " actual=" << count;
1318
1319 return rpcError(rpcBAD_SYNTAX);
1320 }
1321
1322 return (this->*(command.parse))(jvParams);
1323 }
1324 }
1325
1326 // The command could not be found
1327 if (!allowAnyCommand)
1329
1330 return parseAsIs(jvParams);
1331 }
1332};
1333
1334//------------------------------------------------------------------------------
1335
1336//
1337// JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1338// but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1339// unspecified (HTTP errors and contents of 'error').
1340//
1341// 1.0 spec: http://json-rpc.org/wiki/specification
1342// 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1343//
1344
1347 std::string const& strMethod,
1348 Json::Value const& params,
1349 Json::Value const& id)
1350{
1351 Json::Value request;
1352 request[jss::method] = strMethod;
1353 request[jss::params] = params;
1354 request[jss::id] = id;
1355 return to_string(request) + "\n";
1356}
1357
1358namespace {
1359// Special local exception type thrown when request can't be parsed.
1360class RequestNotParseable : public std::runtime_error
1361{
1362 using std::runtime_error::runtime_error; // Inherit constructors
1363};
1364}; // namespace
1365
1367{
1368 explicit RPCCallImp() = default;
1369
1370 // VFALCO NOTE Is this a to-do comment or a doc comment?
1371 // Place the async result somewhere useful.
1372 static void
1373 callRPCHandler(Json::Value* jvOutput, Json::Value const& jvInput)
1374 {
1375 (*jvOutput) = jvInput;
1376 }
1377
1378 static bool
1380 std::function<void(Json::Value const& jvInput)> callbackFuncP,
1381 boost::system::error_code const& ecResult,
1382 int iStatus,
1383 std::string const& strData,
1385 {
1386 if (callbackFuncP)
1387 {
1388 // Only care about the result, if we care to deliver it
1389 // callbackFuncP.
1390
1391 // Receive reply
1392 if (strData.empty())
1393 Throw<std::runtime_error>(
1394 "no response from server. Please "
1395 "ensure that the rippled server is running in another "
1396 "process.");
1397
1398 // Parse reply
1399 JLOG(j.debug()) << "RPC reply: " << strData << std::endl;
1400 if (strData.find("Unable to parse request") == 0 ||
1401 strData.find(jss::invalid_API_version.c_str()) == 0)
1402 Throw<RequestNotParseable>(strData);
1403 Json::Reader reader;
1404 Json::Value jvReply;
1405 if (!reader.parse(strData, jvReply))
1406 Throw<std::runtime_error>("couldn't parse reply from server");
1407
1408 if (!jvReply)
1409 Throw<std::runtime_error>(
1410 "expected reply to have result, error and id properties");
1411
1413
1414 jvResult["result"] = jvReply;
1415
1416 (callbackFuncP)(jvResult);
1417 }
1418
1419 return false;
1420 }
1421
1422 // Build the request.
1423 static void
1425 std::string const& strMethod,
1426 Json::Value const& jvParams,
1428 std::string const& strPath,
1429 boost::asio::streambuf& sb,
1430 std::string const& strHost,
1432 {
1433 JLOG(j.debug()) << "requestRPC: strPath='" << strPath << "'";
1434
1435 std::ostream osRequest(&sb);
1436 osRequest << createHTTPPost(
1437 strHost,
1438 strPath,
1439 JSONRPCRequest(strMethod, jvParams, Json::Value(1)),
1440 headers);
1441 }
1442};
1443
1444//------------------------------------------------------------------------------
1445
1446// Used internally by rpcClient.
1449 std::vector<std::string> const& args,
1450 Json::Value& retParams,
1451 unsigned int apiVersion,
1453{
1454 Json::Value jvRequest(Json::objectValue);
1455
1456 RPCParser rpParser(apiVersion, j);
1457 Json::Value jvRpcParams(Json::arrayValue);
1458
1459 for (int i = 1; i != args.size(); i++)
1460 jvRpcParams.append(args[i]);
1461
1462 retParams = Json::Value(Json::objectValue);
1463
1464 retParams[jss::method] = args[0];
1465 retParams[jss::params] = jvRpcParams;
1466
1467 jvRequest = rpParser.parseCommand(args[0], jvRpcParams, true);
1468
1469 auto insert_api_version = [apiVersion](Json::Value& jr) {
1470 if (jr.isObject() && !jr.isMember(jss::error) &&
1471 !jr.isMember(jss::api_version))
1472 {
1473 jr[jss::api_version] = apiVersion;
1474 }
1475 };
1476
1477 if (jvRequest.isObject())
1478 insert_api_version(jvRequest);
1479 else if (jvRequest.isArray())
1480 std::for_each(jvRequest.begin(), jvRequest.end(), insert_api_version);
1481
1482 JLOG(j.trace()) << "RPC Request: " << jvRequest << std::endl;
1483 return jvRequest;
1484}
1485
1486//------------------------------------------------------------------------------
1487
1490 std::vector<std::string> const& args,
1491 Config const& config,
1492 Logs& logs,
1493 unsigned int apiVersion,
1495{
1496 static_assert(
1497 rpcBAD_SYNTAX == 1 && rpcSUCCESS == 0,
1498 "Expect specific rpc enum values.");
1499 if (args.empty())
1500 return {rpcBAD_SYNTAX, {}}; // rpcBAD_SYNTAX = print usage
1501
1502 int nRet = rpcSUCCESS;
1503 Json::Value jvOutput;
1504 Json::Value jvRequest(Json::objectValue);
1505
1506 try
1507 {
1509 jvRequest =
1510 rpcCmdToJson(args, jvRpc, apiVersion, logs.journal("RPCParser"));
1511
1512 if (jvRequest.isMember(jss::error))
1513 {
1514 jvOutput = jvRequest;
1515 jvOutput["rpc"] = jvRpc;
1516 }
1517 else
1518 {
1520 try
1521 {
1522 setup = setup_ServerHandler(
1523 config,
1524 beast::logstream{logs.journal("HTTPClient").warn()});
1525 }
1526 catch (std::exception const&)
1527 {
1528 // ignore any exceptions, so the command
1529 // line client works without a config file
1530 }
1531
1532 if (config.rpc_ip)
1533 {
1534 setup.client.ip = config.rpc_ip->address().to_string();
1535 setup.client.port = config.rpc_ip->port();
1536 }
1537
1538 Json::Value jvParams(Json::arrayValue);
1539
1540 if (!setup.client.admin_user.empty())
1541 jvRequest["admin_user"] = setup.client.admin_user;
1542
1543 if (!setup.client.admin_password.empty())
1544 jvRequest["admin_password"] = setup.client.admin_password;
1545
1546 if (jvRequest.isObject())
1547 jvParams.append(jvRequest);
1548 else if (jvRequest.isArray())
1549 {
1550 for (Json::UInt i = 0; i < jvRequest.size(); ++i)
1551 jvParams.append(jvRequest[i]);
1552 }
1553
1554 {
1555 boost::asio::io_context isService;
1557 isService,
1558 setup.client.ip,
1559 setup.client.port,
1560 setup.client.user,
1561 setup.client.password,
1562 "",
1563 jvRequest.isMember(
1564 jss::method) // Allow parser to rewrite method.
1565 ? jvRequest[jss::method].asString()
1566 : jvRequest.isArray() ? "batch" : args[0],
1567 jvParams, // Parsed, execute.
1568 setup.client.secure != 0, // Use SSL
1569 config.quiet(),
1570 logs,
1571 std::bind(
1573 &jvOutput,
1574 std::placeholders::_1),
1575 headers);
1576 isService.run(); // This blocks until there are no more
1577 // outstanding async calls.
1578 }
1579 if (jvOutput.isMember("result"))
1580 {
1581 // Had a successful JSON-RPC 2.0 call.
1582 jvOutput = jvOutput["result"];
1583
1584 // jvOutput may report a server side error.
1585 // It should report "status".
1586 }
1587 else
1588 {
1589 // Transport error.
1590 Json::Value jvRpcError = jvOutput;
1591
1592 jvOutput = rpcError(rpcJSON_RPC);
1593 jvOutput["result"] = jvRpcError;
1594 }
1595
1596 // If had an error, supply invocation in result.
1597 if (jvOutput.isMember(jss::error))
1598 {
1599 jvOutput["rpc"] =
1600 jvRpc; // How the command was seen as method + params.
1601 jvOutput["request_sent"] =
1602 jvRequest; // How the command was translated.
1603 }
1604 }
1605
1606 if (jvOutput.isMember(jss::error))
1607 {
1608 jvOutput[jss::status] = "error";
1609 if (jvOutput.isMember(jss::error_code))
1610 nRet = std::stoi(jvOutput[jss::error_code].asString());
1611 else if (jvOutput[jss::error].isMember(jss::error_code))
1612 nRet =
1613 std::stoi(jvOutput[jss::error][jss::error_code].asString());
1614 else
1615 nRet = rpcBAD_SYNTAX;
1616 }
1617
1618 // YYY We could have a command line flag for single line output for
1619 // scripts. YYY We would intercept output here and simplify it.
1620 }
1621 catch (RequestNotParseable& e)
1622 {
1623 jvOutput = rpcError(rpcINVALID_PARAMS);
1624 jvOutput["error_what"] = e.what();
1625 nRet = rpcINVALID_PARAMS;
1626 }
1627 catch (std::exception& e)
1628 {
1629 jvOutput = rpcError(rpcINTERNAL);
1630 jvOutput["error_what"] = e.what();
1631 nRet = rpcINTERNAL;
1632 }
1633
1634 return {nRet, std::move(jvOutput)};
1635}
1636
1637//------------------------------------------------------------------------------
1638
1639namespace RPCCall {
1640
1641int
1643 Config const& config,
1644 std::vector<std::string> const& vCmd,
1645 Logs& logs)
1646{
1647 auto const result =
1648 rpcClient(vCmd, config, logs, RPC::apiCommandLineVersion);
1649
1650 std::cout << result.second.toStyledString();
1651
1652 return result.first;
1653}
1654
1655//------------------------------------------------------------------------------
1656
1657void
1659 boost::asio::io_context& io_context,
1660 std::string const& strIp,
1661 std::uint16_t const iPort,
1662 std::string const& strUsername,
1663 std::string const& strPassword,
1664 std::string const& strPath,
1665 std::string const& strMethod,
1666 Json::Value const& jvParams,
1667 bool const bSSL,
1668 bool const quiet,
1669 Logs& logs,
1670 std::function<void(Json::Value const& jvInput)> callbackFuncP,
1672{
1673 auto j = logs.journal("HTTPClient");
1674
1675 // Connect to localhost
1676 if (!quiet)
1677 {
1678 JLOG(j.info()) << (bSSL ? "Securely connecting to " : "Connecting to ")
1679 << strIp << ":" << iPort << std::endl;
1680 }
1681
1682 // HTTP basic authentication
1683 headers["Authorization"] =
1684 std::string("Basic ") + base64_encode(strUsername + ":" + strPassword);
1685
1686 // Send request
1687
1688 // Number of bytes to try to receive if no
1689 // Content-Length header received
1690 constexpr auto RPC_REPLY_MAX_BYTES = megabytes(256);
1691
1692 using namespace std::chrono_literals;
1693 auto constexpr RPC_WEBHOOK_TIMEOUT = 30s;
1694
1696 bSSL,
1697 io_context,
1698 strIp,
1699 iPort,
1700 std::bind(
1702 strMethod,
1703 jvParams,
1704 headers,
1705 strPath,
1706 std::placeholders::_1,
1707 std::placeholders::_2,
1708 j),
1709 RPC_REPLY_MAX_BYTES,
1710 RPC_WEBHOOK_TIMEOUT,
1711 std::bind(
1713 callbackFuncP,
1714 std::placeholders::_1,
1715 std::placeholders::_2,
1716 std::placeholders::_3,
1717 j),
1718 j);
1719}
1720
1721} // namespace RPCCall
1722
1723} // namespace ripple
T begin(T... args)
T bind(T... args)
Unserialize a JSON document into a Value.
Definition json_reader.h:20
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Represents a JSON value.
Definition json_value.h:131
const_iterator begin() const
bool isArray() const
Value & append(Value const &value)
Append value to array at the end.
UInt size() const
Number of values in array or object.
const_iterator end() const
bool isObjectOrNull() const
Int asInt() const
UInt asUInt() const
bool isObject() const
std::string asString() const
Returns the unquoted string value.
bool isNull() const
isNull() tests to see if this field is null.
bool isMember(char const *key) const
Return true if the object has a member named key.
A generic endpoint for log messages.
Definition Journal.h:41
Stream debug() const
Definition Journal.h:309
Stream trace() const
Severity stream access functions.
Definition Journal.h:303
std::optional< beast::IP::Endpoint > rpc_ip
Definition Config.h:255
bool quiet() const
Definition Config.h:307
static void request(bool bSSL, boost::asio::io_context &io_context, std::string strSite, unsigned short const port, std::function< void(boost::asio::streambuf &sb, std::string const &strHost)> build, std::size_t responseMax, std::chrono::seconds timeout, std::function< bool(boost::system::error_code const &ecResult, int iStatus, std::string const &strData)> complete, beast::Journal &j)
Manages partitions for logging.
Definition Log.h:33
beast::Journal journal(std::string const &name)
Definition Log.cpp:141
Json::Value parseLedger(Json::Value const &jvParams)
Definition RPCCall.cpp:618
Json::Value parseValidationCreate(Json::Value const &jvParams)
Definition RPCCall.cpp:1102
Json::Value parseBookOffers(Json::Value const &jvParams)
Definition RPCCall.cpp:297
Json::Value parseTxHistory(Json::Value const &jvParams)
Definition RPCCall.cpp:1086
Json::Value parseLedgerId(Json::Value const &jvParams)
Definition RPCCall.cpp:647
Json::Value parseCommand(std::string strMethod, Json::Value jvParams, bool allowAnyCommand)
Definition RPCCall.cpp:1205
Json::Value parseGatewayBalances(Json::Value const &jvParams)
Definition RPCCall.cpp:1131
RPCParser(unsigned apiVersion, beast::Journal j)
Definition RPCCall.cpp:1195
Json::Value parseAccountItems(Json::Value const &jvParams)
Definition RPCCall.cpp:707
unsigned const apiVersion_
Definition RPCCall.cpp:73
Json::Value parseJson(Json::Value const &jvParams)
Definition RPCCall.cpp:515
Json::Value parseAccountRaw1(Json::Value const &jvParams)
Definition RPCCall.cpp:843
Json::Value parseFetchInfo(Json::Value const &jvParams)
Definition RPCCall.cpp:208
Json::Value parseSubmitMultiSigned(Json::Value const &jvParams)
Definition RPCCall.cpp:1012
Json::Value parseAccountChannels(Json::Value const &jvParams)
Definition RPCCall.cpp:727
Json::Value parseInternal(Json::Value const &jvParams)
Definition RPCCall.cpp:172
static Json::Value jvParseCurrencyIssuer(std::string const &strCurrencyIssuer)
Definition RPCCall.cpp:102
Json::Value parseSimulate(Json::Value const &jvParams)
Definition RPCCall.cpp:929
Json::Value parseEvented(Json::Value const &jvParams)
Definition RPCCall.cpp:439
Json::Value parseDepositAuthorized(Json::Value const &jvParams)
Definition RPCCall.cpp:417
Json::Value parseAccountTransactions(Json::Value const &jvParams)
Definition RPCCall.cpp:222
Json::Value parseChannelVerify(Json::Value const &jvParams)
Definition RPCCall.cpp:778
Json::Value parseGetCounts(Json::Value const &jvParams)
Definition RPCCall.cpp:473
Json::Value parseLogLevel(Json::Value const &jvParams)
Definition RPCCall.cpp:686
bool isValidJson2(Json::Value const &jv)
Definition RPCCall.cpp:537
Json::Value parseConnect(Json::Value const &jvParams)
Definition RPCCall.cpp:388
static bool validPublicKey(std::string const &strPk, TokenType type=TokenType::AccountPublic)
Definition RPCCall.cpp:139
Json::Value(RPCParser::*)(Json::Value const &jvParams) parseFuncPtr
Definition RPCCall.cpp:158
beast::Journal const j_
Definition RPCCall.cpp:74
Json::Value parseCanDelete(Json::Value const &jvParams)
Definition RPCCall.cpp:370
Json::Value parseWalletPropose(Json::Value const &jvParams)
Definition RPCCall.cpp:1116
Json::Value parseJson2(Json::Value const &jvParams)
Definition RPCCall.cpp:567
Json::Value parseChannelAuthorize(Json::Value const &jvParams)
Definition RPCCall.cpp:734
Json::Value parseAccountCurrencies(Json::Value const &jvParams)
Definition RPCCall.cpp:713
Json::Value parsePeerReservationsDel(Json::Value const &jvParams)
Definition RPCCall.cpp:894
Json::Value parseVault(Json::Value const &jvParams)
Definition RPCCall.cpp:863
Json::Value parseLedgerEntry(Json::Value const &jvParams)
Definition RPCCall.cpp:668
Json::Value parseTx(Json::Value const &jvParams)
Definition RPCCall.cpp:1058
Json::Value parseServerInfo(Json::Value const &jvParams)
Definition RPCCall.cpp:1184
Json::Value parseAsIs(Json::Value const &jvParams)
Definition RPCCall.cpp:161
Json::Value parsePeerReservationsAdd(Json::Value const &jvParams)
Definition RPCCall.cpp:881
Json::Value parseRipplePathFind(Json::Value const &jvParams)
Definition RPCCall.cpp:903
Json::Value parseServerDefinitions(Json::Value const &jvParams)
Definition RPCCall.cpp:1170
Json::Value parseTransactionEntry(Json::Value const &jvParams)
Definition RPCCall.cpp:1031
Json::Value parseFeature(Json::Value const &jvParams)
Definition RPCCall.cpp:446
Json::Value parseManifest(Json::Value const &jvParams)
Definition RPCCall.cpp:188
Json::Value parseAccountRaw2(Json::Value const &jvParams, char const *const acc2Field)
Definition RPCCall.cpp:806
static bool jvParseLedger(Json::Value &jvRequest, std::string const &strLedger)
Definition RPCCall.cpp:79
Json::Value parseSignSubmit(Json::Value const &jvParams)
Definition RPCCall.cpp:960
Json::Value parseAccountLines(Json::Value const &jvParams)
Definition RPCCall.cpp:720
Json::Value parseSignFor(Json::Value const &jvParams)
Definition RPCCall.cpp:486
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:484
T count(T... args)
T empty(T... args)
T end(T... args)
T endl(T... args)
T find_first_not_of(T... args)
T find(T... args)
T find_last_of(T... args)
T for_each(T... args)
T is_same_v
JSON (JavaScript Object Notation).
Definition json_errors.h:6
@ arrayValue
array value (ordered list)
Definition json_value.h:26
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:27
unsigned int UInt
void fromNetwork(boost::asio::io_context &io_context, std::string const &strIp, std::uint16_t const iPort, std::string const &strUsername, std::string const &strPassword, std::string const &strPath, std::string const &strMethod, Json::Value const &jvParams, bool const bSSL, bool const quiet, Logs &logs, std::function< void(Json::Value const &jvInput)> callbackFuncP, std::unordered_map< std::string, std::string > headers)
Definition RPCCall.cpp:1658
int fromCommandLine(Config const &config, std::vector< std::string > const &vCmd, Logs &logs)
Definition RPCCall.cpp:1642
Json::Value invalid_field_error(std::string const &name)
Definition ErrorCodes.h:306
Json::Value make_param_error(std::string const &message)
Returns a new json object that indicates invalid parameters.
Definition ErrorCodes.h:252
static constexpr auto apiCommandLineVersion
Definition ApiVersion.h:45
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::optional< KeyType > keyTypeFromString(std::string const &s)
Definition KeyType.h:15
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:95
constexpr auto megabytes(T value) noexcept
std::pair< int, Json::Value > rpcClient(std::vector< std::string > const &args, Config const &config, Logs &logs, unsigned int apiVersion, std::unordered_map< std::string, std::string > const &headers)
Internal invocation of RPC client.
Definition RPCCall.cpp:1489
static std::string const & systemName()
TokenType
Definition tokens.h:19
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
std::string createHTTPPost(std::string const &strHost, std::string const &strPath, std::string const &strMsg, std::unordered_map< std::string, std::string > const &mapRequestHeaders)
Definition RPCCall.cpp:43
@ rpcNO_EVENTS
Definition ErrorCodes.h:35
@ rpcUNKNOWN_COMMAND
Definition ErrorCodes.h:66
@ rpcACT_MALFORMED
Definition ErrorCodes.h:71
@ rpcBAD_KEY_TYPE
Definition ErrorCodes.h:114
@ rpcCHANNEL_AMT_MALFORMED
Definition ErrorCodes.h:82
@ rpcSUCCESS
Definition ErrorCodes.h:25
@ rpcPUBLIC_MALFORMED
Definition ErrorCodes.h:98
@ rpcINVALID_PARAMS
Definition ErrorCodes.h:65
@ rpcINTERNAL
Definition ErrorCodes.h:111
@ rpcBAD_SYNTAX
Definition ErrorCodes.h:27
@ rpcLGR_IDXS_INVALID
Definition ErrorCodes.h:93
@ rpcCHANNEL_MALFORMED
Definition ErrorCodes.h:81
@ rpcLGR_IDX_MALFORMED
Definition ErrorCodes.h:94
@ rpcJSON_RPC
Definition ErrorCodes.h:28
@ rpcNOT_SYNCED
Definition ErrorCodes.h:48
std::optional< std::uint64_t > to_uint64(std::string const &s)
Json::Value rpcError(int iError)
Definition RPCErr.cpp:12
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
bool isRpcError(Json::Value jvResult)
Definition RPCErr.cpp:21
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition Slice.h:225
ServerHandler::Setup setup_ServerHandler(Config const &config, std::ostream &&log)
std::string base64_encode(std::uint8_t const *data, std::size_t len)
std::string JSONRPCRequest(std::string const &strMethod, Json::Value const &params, Json::Value const &id)
Definition RPCCall.cpp:1346
Json::Value rpcCmdToJson(std::vector< std::string > const &args, Json::Value &retParams, unsigned int apiVersion, beast::Journal j)
Definition RPCCall.cpp:1448
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
T size(T... args)
T stoi(T... args)
T str(T... args)
static void callRPCHandler(Json::Value *jvOutput, Json::Value const &jvInput)
Definition RPCCall.cpp:1373
static bool onResponse(std::function< void(Json::Value const &jvInput)> callbackFuncP, boost::system::error_code const &ecResult, int iStatus, std::string const &strData, beast::Journal j)
Definition RPCCall.cpp:1379
RPCCallImp()=default
static void onRequest(std::string const &strMethod, Json::Value const &jvParams, std::unordered_map< std::string, std::string > const &headers, std::string const &strPath, boost::asio::streambuf &sb, std::string const &strHost, beast::Journal j)
Definition RPCCall.cpp:1424