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