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