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