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 // simulate any transaction on the network
913 //
914 // simulate <tx_blob> [binary]
915 // simulate <tx_json> [binary]
917 parseSimulate(Json::Value const& jvParams)
918 {
919 Json::Value txJSON;
920 Json::Reader reader;
922
923 if (reader.parse(jvParams[0u].asString(), txJSON))
924 {
925 jvRequest[jss::tx_json] = txJSON;
926 }
927 else
928 {
929 jvRequest[jss::tx_blob] = jvParams[0u].asString();
930 }
931
932 if (jvParams.size() == 2)
933 {
934 if (!jvParams[1u].isString() || jvParams[1u].asString() != "binary")
936 jvRequest[jss::binary] = true;
937 }
938
939 return jvRequest;
940 }
941
942 // sign/submit any transaction to the network
943 //
944 // sign <private_key> <json> offline
945 // submit <private_key> <json>
946 // submit <tx_blob>
949 {
950 Json::Value txJSON;
951 Json::Reader reader;
952 bool const bOffline =
953 3 == jvParams.size() && jvParams[2u].asString() == "offline";
954
955 if (1 == jvParams.size())
956 {
957 // Submitting tx_blob
958
960
961 jvRequest[jss::tx_blob] = jvParams[0u].asString();
962
963 return jvRequest;
964 }
965 else if (
966 (2 == jvParams.size() || bOffline) &&
967 reader.parse(jvParams[1u].asString(), txJSON))
968 {
969 // Signing or submitting tx_json.
971
972 jvRequest[jss::secret] = jvParams[0u].asString();
973 jvRequest[jss::tx_json] = txJSON;
974
975 if (bOffline)
976 jvRequest[jss::offline] = true;
977
978 return jvRequest;
979 }
980
982 }
983
984 // submit any multisigned transaction to the network
985 //
986 // submit_multisigned <json>
989 {
990 if (1 == jvParams.size())
991 {
992 Json::Value txJSON;
993 Json::Reader reader;
994 if (reader.parse(jvParams[0u].asString(), txJSON))
995 {
997 jvRequest[jss::tx_json] = txJSON;
998 return jvRequest;
999 }
1000 }
1001
1003 }
1004
1005 // transaction_entry <tx_hash> <ledger_hash/ledger_index>
1008 {
1009 // Parameter count should have already been verified.
1010 XRPL_ASSERT(
1011 jvParams.size() == 2,
1012 "ripple::RPCParser::parseTransactionEntry : valid parameter count");
1013
1014 std::string const txHash = jvParams[0u].asString();
1015 if (txHash.length() != 64)
1017
1018 Json::Value jvRequest{Json::objectValue};
1019 jvRequest[jss::tx_hash] = txHash;
1020
1021 jvParseLedger(jvRequest, jvParams[1u].asString());
1022
1023 // jvParseLedger inserts a "ledger_index" of 0 if it doesn't
1024 // find a match.
1025 if (jvRequest.isMember(jss::ledger_index) &&
1026 jvRequest[jss::ledger_index] == 0)
1028
1029 return jvRequest;
1030 }
1031
1032 // tx <transaction_id>
1034 parseTx(Json::Value const& jvParams)
1035 {
1036 Json::Value jvRequest{Json::objectValue};
1037
1038 if (jvParams.size() == 2 || jvParams.size() == 4)
1039 {
1040 if (jvParams[1u].asString() == jss::binary)
1041 jvRequest[jss::binary] = true;
1042 }
1043
1044 if (jvParams.size() >= 3)
1045 {
1046 const auto offset = jvParams.size() == 3 ? 0 : 1;
1047
1048 jvRequest[jss::min_ledger] = jvParams[1u + offset].asString();
1049 jvRequest[jss::max_ledger] = jvParams[2u + offset].asString();
1050 }
1051
1052 if (jvParams[0u].asString().length() == 16)
1053 jvRequest[jss::ctid] = jvParams[0u].asString();
1054 else
1055 jvRequest[jss::transaction] = jvParams[0u].asString();
1056
1057 return jvRequest;
1058 }
1059
1060 // tx_history <index>
1063 {
1064 Json::Value jvRequest{Json::objectValue};
1065
1066 jvRequest[jss::start] = jvParams[0u].asUInt();
1067
1068 return jvRequest;
1069 }
1070
1071 // validation_create [<pass_phrase>|<seed>|<seed_key>]
1072 //
1073 // NOTE: It is poor security to specify secret information on the command
1074 // line. This information might be saved in the command shell history file
1075 // (e.g. .bash_history) and it may be leaked via the process status command
1076 // (i.e. ps).
1079 {
1080 Json::Value jvRequest{Json::objectValue};
1081
1082 if (jvParams.size())
1083 jvRequest[jss::secret] = jvParams[0u].asString();
1084
1085 return jvRequest;
1086 }
1087
1088 // wallet_propose [<passphrase>]
1089 // <passphrase> is only for testing. Master seeds should only be generated
1090 // randomly.
1093 {
1094 Json::Value jvRequest{Json::objectValue};
1095
1096 if (jvParams.size())
1097 jvRequest[jss::passphrase] = jvParams[0u].asString();
1098
1099 return jvRequest;
1100 }
1101
1102 // parse gateway balances
1103 // gateway_balances [<ledger>] <issuer_account> [ <hotwallet> [ <hotwallet>
1104 // ]]
1105
1108 {
1109 unsigned int index = 0;
1110 const unsigned int size = jvParams.size();
1111
1112 Json::Value jvRequest{Json::objectValue};
1113
1114 std::string param = jvParams[index++].asString();
1115 if (param.empty())
1116 return RPC::make_param_error("Invalid first parameter");
1117
1118 if (param[0] != 'r')
1119 {
1120 if (param.size() == 64)
1121 jvRequest[jss::ledger_hash] = param;
1122 else
1123 jvRequest[jss::ledger_index] = param;
1124
1125 if (size <= index)
1126 return RPC::make_param_error("Invalid hotwallet");
1127
1128 param = jvParams[index++].asString();
1129 }
1130
1131 jvRequest[jss::account] = param;
1132
1133 if (index < size)
1134 {
1135 Json::Value& hotWallets =
1136 (jvRequest["hotwallet"] = Json::arrayValue);
1137 while (index < size)
1138 hotWallets.append(jvParams[index++].asString());
1139 }
1140
1141 return jvRequest;
1142 }
1143
1144 // server_definitions [hash]
1147 {
1148 Json::Value jvRequest{Json::objectValue};
1149
1150 if (jvParams.size() == 1)
1151 {
1152 jvRequest[jss::hash] = jvParams[0u].asString();
1153 }
1154
1155 return jvRequest;
1156 }
1157
1158 // server_info [counters]
1161 {
1162 Json::Value jvRequest(Json::objectValue);
1163 if (jvParams.size() == 1 && jvParams[0u].asString() == "counters")
1164 jvRequest[jss::counters] = true;
1165 return jvRequest;
1166 }
1167
1168public:
1169 //--------------------------------------------------------------------------
1170
1171 explicit RPCParser(unsigned apiVersion, beast::Journal j)
1172 : apiVersion_(apiVersion), j_(j)
1173 {
1174 }
1175
1176 //--------------------------------------------------------------------------
1177
1178 // Convert a rpc method and params to a request.
1179 // <-- { method: xyz, params: [... ] } or { error: ..., ... }
1182 std::string strMethod,
1183 Json::Value jvParams,
1184 bool allowAnyCommand)
1185 {
1186 if (auto stream = j_.trace())
1187 {
1188 stream << "Method: '" << strMethod << "'";
1189 stream << "Params: " << jvParams;
1190 }
1191
1192 struct Command
1193 {
1194 const char* name;
1195 parseFuncPtr parse;
1196 int minParams;
1197 int maxParams;
1198 };
1199
1200 static constexpr Command commands[] = {
1201 // Request-response methods
1202 // - Returns an error, or the request.
1203 // - To modify the method, provide a new method in the request.
1204 {"account_currencies", &RPCParser::parseAccountCurrencies, 1, 3},
1205 {"account_info", &RPCParser::parseAccountItems, 1, 3},
1206 {"account_lines", &RPCParser::parseAccountLines, 1, 5},
1207 {"account_channels", &RPCParser::parseAccountChannels, 1, 3},
1208 {"account_nfts", &RPCParser::parseAccountItems, 1, 5},
1209 {"account_objects", &RPCParser::parseAccountItems, 1, 5},
1210 {"account_offers", &RPCParser::parseAccountItems, 1, 4},
1211 {"account_tx", &RPCParser::parseAccountTransactions, 1, 8},
1212 {"amm_info", &RPCParser::parseAsIs, 1, 2},
1213 {"book_changes", &RPCParser::parseLedgerId, 1, 1},
1214 {"book_offers", &RPCParser::parseBookOffers, 2, 7},
1215 {"can_delete", &RPCParser::parseCanDelete, 0, 1},
1216 {"channel_authorize", &RPCParser::parseChannelAuthorize, 3, 4},
1217 {"channel_verify", &RPCParser::parseChannelVerify, 4, 4},
1218 {"connect", &RPCParser::parseConnect, 1, 2},
1219 {"consensus_info", &RPCParser::parseAsIs, 0, 0},
1220 {"deposit_authorized", &RPCParser::parseDepositAuthorized, 2, 11},
1221 {"feature", &RPCParser::parseFeature, 0, 2},
1222 {"fetch_info", &RPCParser::parseFetchInfo, 0, 1},
1223 {"gateway_balances", &RPCParser::parseGatewayBalances, 1, -1},
1224 {"get_counts", &RPCParser::parseGetCounts, 0, 1},
1225 {"json", &RPCParser::parseJson, 2, 2},
1226 {"json2", &RPCParser::parseJson2, 1, 1},
1227 {"ledger", &RPCParser::parseLedger, 0, 2},
1228 {"ledger_accept", &RPCParser::parseAsIs, 0, 0},
1229 {"ledger_closed", &RPCParser::parseAsIs, 0, 0},
1230 {"ledger_current", &RPCParser::parseAsIs, 0, 0},
1231 {"ledger_entry", &RPCParser::parseLedgerEntry, 1, 2},
1232 {"ledger_header", &RPCParser::parseLedgerId, 1, 1},
1233 {"ledger_request", &RPCParser::parseLedgerId, 1, 1},
1234 {"log_level", &RPCParser::parseLogLevel, 0, 2},
1235 {"logrotate", &RPCParser::parseAsIs, 0, 0},
1236 {"manifest", &RPCParser::parseManifest, 1, 1},
1237 {"owner_info", &RPCParser::parseAccountItems, 1, 3},
1238 {"peers", &RPCParser::parseAsIs, 0, 0},
1239 {"ping", &RPCParser::parseAsIs, 0, 0},
1240 {"print", &RPCParser::parseAsIs, 0, 1},
1241 // { "profile", &RPCParser::parseProfile, 1, 9
1242 // },
1243 {"random", &RPCParser::parseAsIs, 0, 0},
1244 {"peer_reservations_add",
1246 1,
1247 2},
1248 {"peer_reservations_del",
1250 1,
1251 1},
1252 {"peer_reservations_list", &RPCParser::parseAsIs, 0, 0},
1253 {"ripple_path_find", &RPCParser::parseRipplePathFind, 1, 2},
1254 {"server_definitions", &RPCParser::parseServerDefinitions, 0, 1},
1255 {"server_info", &RPCParser::parseServerInfo, 0, 1},
1256 {"server_state", &RPCParser::parseServerInfo, 0, 1},
1257 {"sign", &RPCParser::parseSignSubmit, 2, 3},
1258 {"sign_for", &RPCParser::parseSignFor, 3, 4},
1259 {"stop", &RPCParser::parseAsIs, 0, 0},
1260 {"simulate", &RPCParser::parseSimulate, 1, 2},
1261 {"submit", &RPCParser::parseSignSubmit, 1, 3},
1262 {"submit_multisigned", &RPCParser::parseSubmitMultiSigned, 1, 1},
1263 {"transaction_entry", &RPCParser::parseTransactionEntry, 2, 2},
1264 {"tx", &RPCParser::parseTx, 1, 4},
1265 {"tx_history", &RPCParser::parseTxHistory, 1, 1},
1266 {"unl_list", &RPCParser::parseAsIs, 0, 0},
1267 {"validation_create", &RPCParser::parseValidationCreate, 0, 1},
1268 {"validator_info", &RPCParser::parseAsIs, 0, 0},
1269 {"version", &RPCParser::parseAsIs, 0, 0},
1270 {"wallet_propose", &RPCParser::parseWalletPropose, 0, 1},
1271 {"internal", &RPCParser::parseInternal, 1, -1},
1272
1273 // Evented methods
1274 {"path_find", &RPCParser::parseEvented, -1, -1},
1275 {"subscribe", &RPCParser::parseEvented, -1, -1},
1276 {"unsubscribe", &RPCParser::parseEvented, -1, -1},
1277 };
1278
1279 auto const count = jvParams.size();
1280
1281 for (auto const& command : commands)
1282 {
1283 if (strMethod == command.name)
1284 {
1285 if ((command.minParams >= 0 && count < command.minParams) ||
1286 (command.maxParams >= 0 && count > command.maxParams))
1287 {
1288 JLOG(j_.debug())
1289 << "Wrong number of parameters for " << command.name
1290 << " minimum=" << command.minParams
1291 << " maximum=" << command.maxParams
1292 << " actual=" << count;
1293
1294 return rpcError(rpcBAD_SYNTAX);
1295 }
1296
1297 return (this->*(command.parse))(jvParams);
1298 }
1299 }
1300
1301 // The command could not be found
1302 if (!allowAnyCommand)
1304
1305 return parseAsIs(jvParams);
1306 }
1307};
1308
1309//------------------------------------------------------------------------------
1310
1311//
1312// JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1313// but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1314// unspecified (HTTP errors and contents of 'error').
1315//
1316// 1.0 spec: http://json-rpc.org/wiki/specification
1317// 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1318//
1319
1322 std::string const& strMethod,
1323 Json::Value const& params,
1324 Json::Value const& id)
1325{
1326 Json::Value request;
1327 request[jss::method] = strMethod;
1328 request[jss::params] = params;
1329 request[jss::id] = id;
1330 return to_string(request) + "\n";
1331}
1332
1333namespace {
1334// Special local exception type thrown when request can't be parsed.
1335class RequestNotParseable : public std::runtime_error
1336{
1337 using std::runtime_error::runtime_error; // Inherit constructors
1338};
1339}; // namespace
1340
1342{
1343 explicit RPCCallImp() = default;
1344
1345 // VFALCO NOTE Is this a to-do comment or a doc comment?
1346 // Place the async result somewhere useful.
1347 static void
1348 callRPCHandler(Json::Value* jvOutput, Json::Value const& jvInput)
1349 {
1350 (*jvOutput) = jvInput;
1351 }
1352
1353 static bool
1355 std::function<void(Json::Value const& jvInput)> callbackFuncP,
1356 const boost::system::error_code& ecResult,
1357 int iStatus,
1358 std::string const& strData,
1360 {
1361 if (callbackFuncP)
1362 {
1363 // Only care about the result, if we care to deliver it
1364 // callbackFuncP.
1365
1366 // Receive reply
1367 if (strData.empty())
1368 Throw<std::runtime_error>(
1369 "no response from server. Please "
1370 "ensure that the rippled server is running in another "
1371 "process.");
1372
1373 // Parse reply
1374 JLOG(j.debug()) << "RPC reply: " << strData << std::endl;
1375 if (strData.find("Unable to parse request") == 0 ||
1376 strData.find(jss::invalid_API_version.c_str()) == 0)
1377 Throw<RequestNotParseable>(strData);
1378 Json::Reader reader;
1379 Json::Value jvReply;
1380 if (!reader.parse(strData, jvReply))
1381 Throw<std::runtime_error>("couldn't parse reply from server");
1382
1383 if (!jvReply)
1384 Throw<std::runtime_error>(
1385 "expected reply to have result, error and id properties");
1386
1388
1389 jvResult["result"] = jvReply;
1390
1391 (callbackFuncP)(jvResult);
1392 }
1393
1394 return false;
1395 }
1396
1397 // Build the request.
1398 static void
1400 std::string const& strMethod,
1401 Json::Value const& jvParams,
1403 std::string const& strPath,
1404 boost::asio::streambuf& sb,
1405 std::string const& strHost,
1407 {
1408 JLOG(j.debug()) << "requestRPC: strPath='" << strPath << "'";
1409
1410 std::ostream osRequest(&sb);
1411 osRequest << createHTTPPost(
1412 strHost,
1413 strPath,
1414 JSONRPCRequest(strMethod, jvParams, Json::Value(1)),
1415 headers);
1416 }
1417};
1418
1419//------------------------------------------------------------------------------
1420
1421// Used internally by rpcClient.
1424 std::vector<std::string> const& args,
1425 Json::Value& retParams,
1426 unsigned int apiVersion,
1428{
1429 Json::Value jvRequest(Json::objectValue);
1430
1431 RPCParser rpParser(apiVersion, j);
1432 Json::Value jvRpcParams(Json::arrayValue);
1433
1434 for (int i = 1; i != args.size(); i++)
1435 jvRpcParams.append(args[i]);
1436
1437 retParams = Json::Value(Json::objectValue);
1438
1439 retParams[jss::method] = args[0];
1440 retParams[jss::params] = jvRpcParams;
1441
1442 jvRequest = rpParser.parseCommand(args[0], jvRpcParams, true);
1443
1444 auto insert_api_version = [apiVersion](Json::Value& jr) {
1445 if (jr.isObject() && !jr.isMember(jss::error) &&
1446 !jr.isMember(jss::api_version))
1447 {
1448 jr[jss::api_version] = apiVersion;
1449 }
1450 };
1451
1452 if (jvRequest.isObject())
1453 insert_api_version(jvRequest);
1454 else if (jvRequest.isArray())
1455 std::for_each(jvRequest.begin(), jvRequest.end(), insert_api_version);
1456
1457 JLOG(j.trace()) << "RPC Request: " << jvRequest << std::endl;
1458 return jvRequest;
1459}
1460
1461//------------------------------------------------------------------------------
1462
1465 std::vector<std::string> const& args,
1466 Config const& config,
1467 Logs& logs,
1468 unsigned int apiVersion,
1470{
1471 static_assert(
1472 rpcBAD_SYNTAX == 1 && rpcSUCCESS == 0,
1473 "Expect specific rpc enum values.");
1474 if (args.empty())
1475 return {rpcBAD_SYNTAX, {}}; // rpcBAD_SYNTAX = print usage
1476
1477 int nRet = rpcSUCCESS;
1478 Json::Value jvOutput;
1479 Json::Value jvRequest(Json::objectValue);
1480
1481 try
1482 {
1484 jvRequest =
1485 rpcCmdToJson(args, jvRpc, apiVersion, logs.journal("RPCParser"));
1486
1487 if (jvRequest.isMember(jss::error))
1488 {
1489 jvOutput = jvRequest;
1490 jvOutput["rpc"] = jvRpc;
1491 }
1492 else
1493 {
1495 try
1496 {
1497 setup = setup_ServerHandler(
1498 config,
1499 beast::logstream{logs.journal("HTTPClient").warn()});
1500 }
1501 catch (std::exception const&)
1502 {
1503 // ignore any exceptions, so the command
1504 // line client works without a config file
1505 }
1506
1507 if (config.rpc_ip)
1508 {
1509 setup.client.ip = config.rpc_ip->address().to_string();
1510 setup.client.port = config.rpc_ip->port();
1511 }
1512
1513 Json::Value jvParams(Json::arrayValue);
1514
1515 if (!setup.client.admin_user.empty())
1516 jvRequest["admin_user"] = setup.client.admin_user;
1517
1518 if (!setup.client.admin_password.empty())
1519 jvRequest["admin_password"] = setup.client.admin_password;
1520
1521 if (jvRequest.isObject())
1522 jvParams.append(jvRequest);
1523 else if (jvRequest.isArray())
1524 {
1525 for (Json::UInt i = 0; i < jvRequest.size(); ++i)
1526 jvParams.append(jvRequest[i]);
1527 }
1528
1529 {
1530 boost::asio::io_service isService;
1532 isService,
1533 setup.client.ip,
1534 setup.client.port,
1535 setup.client.user,
1536 setup.client.password,
1537 "",
1538 jvRequest.isMember(
1539 jss::method) // Allow parser to rewrite method.
1540 ? jvRequest[jss::method].asString()
1541 : jvRequest.isArray() ? "batch" : args[0],
1542 jvParams, // Parsed, execute.
1543 setup.client.secure != 0, // Use SSL
1544 config.quiet(),
1545 logs,
1546 std::bind(
1548 &jvOutput,
1549 std::placeholders::_1),
1550 headers);
1551 isService.run(); // This blocks until there are no more
1552 // outstanding async calls.
1553 }
1554 if (jvOutput.isMember("result"))
1555 {
1556 // Had a successful JSON-RPC 2.0 call.
1557 jvOutput = jvOutput["result"];
1558
1559 // jvOutput may report a server side error.
1560 // It should report "status".
1561 }
1562 else
1563 {
1564 // Transport error.
1565 Json::Value jvRpcError = jvOutput;
1566
1567 jvOutput = rpcError(rpcJSON_RPC);
1568 jvOutput["result"] = jvRpcError;
1569 }
1570
1571 // If had an error, supply invocation in result.
1572 if (jvOutput.isMember(jss::error))
1573 {
1574 jvOutput["rpc"] =
1575 jvRpc; // How the command was seen as method + params.
1576 jvOutput["request_sent"] =
1577 jvRequest; // How the command was translated.
1578 }
1579 }
1580
1581 if (jvOutput.isMember(jss::error))
1582 {
1583 jvOutput[jss::status] = "error";
1584 if (jvOutput.isMember(jss::error_code))
1585 nRet = std::stoi(jvOutput[jss::error_code].asString());
1586 else if (jvOutput[jss::error].isMember(jss::error_code))
1587 nRet =
1588 std::stoi(jvOutput[jss::error][jss::error_code].asString());
1589 else
1590 nRet = rpcBAD_SYNTAX;
1591 }
1592
1593 // YYY We could have a command line flag for single line output for
1594 // scripts. YYY We would intercept output here and simplify it.
1595 }
1596 catch (RequestNotParseable& e)
1597 {
1598 jvOutput = rpcError(rpcINVALID_PARAMS);
1599 jvOutput["error_what"] = e.what();
1600 nRet = rpcINVALID_PARAMS;
1601 }
1602 catch (std::exception& e)
1603 {
1604 jvOutput = rpcError(rpcINTERNAL);
1605 jvOutput["error_what"] = e.what();
1606 nRet = rpcINTERNAL;
1607 }
1608
1609 return {nRet, std::move(jvOutput)};
1610}
1611
1612//------------------------------------------------------------------------------
1613
1614namespace RPCCall {
1615
1616int
1618 Config const& config,
1619 const std::vector<std::string>& vCmd,
1620 Logs& logs)
1621{
1622 auto const result =
1623 rpcClient(vCmd, config, logs, RPC::apiCommandLineVersion);
1624
1625 std::cout << result.second.toStyledString();
1626
1627 return result.first;
1628}
1629
1630//------------------------------------------------------------------------------
1631
1632void
1634 boost::asio::io_service& io_service,
1635 std::string const& strIp,
1636 const std::uint16_t iPort,
1637 std::string const& strUsername,
1638 std::string const& strPassword,
1639 std::string const& strPath,
1640 std::string const& strMethod,
1641 Json::Value const& jvParams,
1642 const bool bSSL,
1643 const bool quiet,
1644 Logs& logs,
1645 std::function<void(Json::Value const& jvInput)> callbackFuncP,
1647{
1648 auto j = logs.journal("HTTPClient");
1649
1650 // Connect to localhost
1651 if (!quiet)
1652 {
1653 JLOG(j.info()) << (bSSL ? "Securely connecting to " : "Connecting to ")
1654 << strIp << ":" << iPort << std::endl;
1655 }
1656
1657 // HTTP basic authentication
1658 headers["Authorization"] =
1659 std::string("Basic ") + base64_encode(strUsername + ":" + strPassword);
1660
1661 // Send request
1662
1663 // Number of bytes to try to receive if no
1664 // Content-Length header received
1665 constexpr auto RPC_REPLY_MAX_BYTES = megabytes(256);
1666
1667 using namespace std::chrono_literals;
1668 auto constexpr RPC_NOTIFY = 10min;
1669
1671 bSSL,
1672 io_service,
1673 strIp,
1674 iPort,
1675 std::bind(
1677 strMethod,
1678 jvParams,
1679 headers,
1680 strPath,
1681 std::placeholders::_1,
1682 std::placeholders::_2,
1683 j),
1684 RPC_REPLY_MAX_BYTES,
1685 RPC_NOTIFY,
1686 std::bind(
1688 callbackFuncP,
1689 std::placeholders::_1,
1690 std::placeholders::_2,
1691 std::placeholders::_3,
1692 j),
1693 j);
1694}
1695
1696} // namespace RPCCall
1697
1698} // 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:1078
Json::Value parseBookOffers(Json::Value const &jvParams)
Definition: RPCCall.cpp:318
Json::Value parseTxHistory(Json::Value const &jvParams)
Definition: RPCCall.cpp:1062
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:1181
Json::Value parseGatewayBalances(Json::Value const &jvParams)
Definition: RPCCall.cpp:1107
RPCParser(unsigned apiVersion, beast::Journal j)
Definition: RPCCall.cpp:1171
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:988
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 parseSimulate(Json::Value const &jvParams)
Definition: RPCCall.cpp:917
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:1092
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:1034
Json::Value parseServerInfo(Json::Value const &jvParams)
Definition: RPCCall.cpp:1160
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:1146
Json::Value parseTransactionEntry(Json::Value const &jvParams)
Definition: RPCCall.cpp:1007
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:948
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:1617
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:1633
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: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:1464
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:1321
Json::Value rpcCmdToJson(std::vector< std::string > const &args, Json::Value &retParams, unsigned int apiVersion, beast::Journal j)
Definition: RPCCall.cpp:1423
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:1348
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:1399
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:1354