xrpld
Loading...
Searching...
No Matches
RPCCall.cpp
1#include <xrpld/rpc/RPCCall.h>
2
3#include <xrpld/core/Config.h>
4#include <xrpld/rpc/MethodNames.h>
5#include <xrpld/rpc/ServerHandler.h>
6
7#include <xrpl/basics/ByteUtilities.h>
8#include <xrpl/basics/Log.h>
9#include <xrpl/basics/Slice.h>
10#include <xrpl/basics/StringUtilities.h>
11#include <xrpl/basics/base64.h>
12#include <xrpl/basics/base_uint.h>
13#include <xrpl/basics/contract.h>
14#include <xrpl/beast/core/LexicalCast.h>
15#include <xrpl/beast/utility/Journal.h>
16#include <xrpl/beast/utility/Zero.h>
17#include <xrpl/beast/utility/instrumentation.h>
18#include <xrpl/json/json_forwards.h>
19#include <xrpl/json/json_reader.h>
20#include <xrpl/json/json_value.h>
21#include <xrpl/json/to_string.h>
22#include <xrpl/net/HTTPClient.h>
23#include <xrpl/protocol/AccountID.h>
24#include <xrpl/protocol/ApiVersion.h>
25#include <xrpl/protocol/ErrorCodes.h>
26#include <xrpl/protocol/KeyType.h>
27#include <xrpl/protocol/PublicKey.h>
28#include <xrpl/protocol/RPCErr.h>
29#include <xrpl/protocol/SystemParameters.h>
30#include <xrpl/protocol/jss.h>
31#include <xrpl/protocol/tokens.h>
32
33#include <boost/algorithm/string/predicate.hpp>
34#include <boost/asio/io_context.hpp>
35#include <boost/asio/streambuf.hpp>
36#include <boost/regex/v5/regex.hpp>
37#include <boost/regex/v5/regex_match.hpp>
38#include <boost/system/detail/error_code.hpp>
39
40#include <algorithm>
41#include <array>
42#include <chrono>
43#include <cstddef>
44#include <cstdint>
45#include <exception>
46#include <functional>
47#include <iostream>
48#include <limits>
49#include <optional>
50#include <span>
51#include <sstream>
52#include <stdexcept>
53#include <string>
54#include <string_view>
55#include <unordered_map>
56#include <utility>
57#include <vector>
58
59namespace xrpl {
60
61class RPCParser;
62
63namespace {
64
76class Parse
77{
78public:
79 using Function = json::Value (RPCParser::*)(json::Value const& jvParams);
80
87 template <Function Fn>
88 static constexpr Parse
89 of() noexcept
90 {
91 return Parse{Fn};
92 }
93
104 json::Value
105 operator()(RPCParser& parser, json::Value const& jvParams) const;
106
107private:
108 constexpr explicit Parse(Function fn) noexcept : fn_(fn)
109 {
110 }
111
112 Function fn_;
113};
114
115// One command the command line accepts: the method it names, the parser that
116// turns arguments into a request, and how many arguments that parser needs.
117//
118// Declared out here, rather than nested in RPCParser, so that the defaults
119// below can be used: a default member initializer is not available while the
120// enclosing class is still incomplete, which is when the table is built.
121struct Command
122{
123 // For a command that accepts any number of parameters.
124 static constexpr unsigned kUnlimitedParams = std::numeric_limits<unsigned>::max();
125
126 std::string_view name;
127 Parse parse;
128 unsigned minParams = 0;
129 unsigned maxParams = kUnlimitedParams;
130};
131
132} // namespace
133
134//
135// HTTP protocol
136//
137// This ain't Apache. We're just using HTTP header for the length field
138// and to be compatible with other JSON-RPC implementations.
139//
140
141std::string
143 std::string const& strHost,
144 std::string const& strPath,
145 std::string const& strMsg,
146 std::unordered_map<std::string, std::string> const& mapRequestHeaders)
147{
149
150 // CHECKME this uses a different version than the replies below use. Is
151 // this by design or an accident or should it be using
152 // build_info::getFullVersionString () as well?
153
154 s << "POST " << (strPath.empty() ? "/" : strPath) << " HTTP/1.0\r\n"
155 << "User-Agent: " << systemName() << "-json-rpc/v1\r\n"
156 << "Host: " << strHost << "\r\n"
157 << "Content-Type: application/json\r\n"
158 << "Content-Length: " << strMsg.size() << "\r\n"
159 << "Accept: application/json\r\n";
160
161 for (auto const& [k, v] : mapRequestHeaders)
162 s << k << ": " << v << "\r\n";
163
164 s << "\r\n" << strMsg;
165
166 return s.str();
167}
168
170{
171private:
172 unsigned const apiVersion_;
174
175 // TODO New routine for parsing ledger parameters, other routines should
176 // standardize on this.
177 static bool
178 jvParseLedger(json::Value& jvRequest, std::string const& strLedger)
179 {
180 if (strLedger == "current" || strLedger == "closed" || strLedger == "validated")
181 {
182 jvRequest[jss::ledger_index] = strLedger;
183 }
184 else if (strLedger.length() == 64)
185 {
186 // YYY Could confirm this is a UInt256.
187 jvRequest[jss::ledger_hash] = strLedger;
188 }
189 else
190 {
191 jvRequest[jss::ledger_index] = beast::lexicalCast<std::uint32_t>(strLedger);
192 }
193
194 return true;
195 }
196
197 // Build a object { "currency" : "XYZ", "issuer" : "rXYX" }
198 static json::Value
199 jvParseCurrencyIssuer(std::string const& strCurrencyIssuer)
200 {
201 // Matches a sequence of 3 characters from
202 // `xrpl::detail::isoCharSet` (the currency),
203 // optionally followed by a forward slash and some other characters
204 // (the issuer).
205 // https://www.boost.org/doc/libs/1_82_0/libs/regex/doc/html/boost_regex/syntax/perl_syntax.html
206 static boost::regex const kReCurIss("\\`([][:alnum:]<>(){}[|?!@#$%^&*]{3})(?:/(.+))?\\'");
207
208 boost::smatch smMatch;
209
210 if (boost::regex_match(strCurrencyIssuer, smMatch, kReCurIss))
211 {
213 std::string const strCurrency = smMatch[1];
214 std::string const strIssuer = smMatch[2];
215
216 jvResult[jss::currency] = strCurrency;
217
218 if (!strIssuer.empty())
219 {
220 // Could confirm issuer is a valid XRPL address.
221 jvResult[jss::issuer] = strIssuer;
222 }
223
224 return jvResult;
225 }
226
227 return rpc::makeParamError(
228 std::string("Invalid currency/issuer '") + strCurrencyIssuer + "'");
229 }
230
231 static bool
233 {
234 if (parseBase58<xrpl::PublicKey>(type, strPk))
235 return true;
236
237 auto pkHex = strUnHex(strPk);
238 if (!pkHex)
239 return false;
240
241 if (!publicKeyType(makeSlice(*pkHex)))
242 return false;
243
244 return true;
245 }
246
247private:
248 using ParseFuncPtr = json::Value (RPCParser::*)(json::Value const& jvParams);
249
251 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
252 parseAsIs(json::Value const& jvParams)
253 {
255
256 if (jvParams.isArray() && (jvParams.size() > 0))
257 v[jss::params] = jvParams;
258
259 return v;
260 }
261
263 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
264 parseInternal(json::Value const& jvParams)
265 {
267 v[jss::internal_command] = jvParams[0u];
268
270
271 for (unsigned i = 1; i < jvParams.size(); ++i)
272 params.append(jvParams[i]);
273
274 v[jss::params] = params;
275
276 return v;
277 }
278
280 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
281 parseManifest(json::Value const& jvParams)
282 {
283 if (jvParams.size() == 1)
284 {
286
287 std::string const strPk = jvParams[0u].asString();
290
291 jvRequest[jss::public_key] = strPk;
292
293 return jvRequest;
294 }
295
297 }
298
299 // fetch_info [clear]
301 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
303 {
305 unsigned int const iParams = jvParams.size();
306
307 if (iParams != 0)
308 jvRequest[jvParams[0u].asString()] = true;
309
310 return jvRequest;
311 }
312
313 // account_tx accountID [ledger_min [ledger_max [limit [offset]]]] [binary]
314 // [count] [descending]
316 // NOLINTNEXTLINE(readability-make-member-function-const)
318 {
320 unsigned int iParams = jvParams.size();
321
322 auto const account = parseBase58<AccountID>(jvParams[0u].asString());
323 if (!account)
325
326 jvRequest[jss::account] = toBase58(*account);
327
328 bool bDone = false;
329
330 while (!bDone && iParams >= 2)
331 {
332 // VFALCO Why is json::StaticString appearing on the right side?
333 if (jvParams[iParams - 1].asString() == jss::binary)
334 {
335 jvRequest[jss::binary] = true;
336 --iParams;
337 }
338 else if (jvParams[iParams - 1].asString() == jss::count)
339 {
340 jvRequest[jss::count] = true;
341 --iParams;
342 }
343 else if (jvParams[iParams - 1].asString() == jss::descending)
344 {
345 jvRequest[jss::descending] = true;
346 --iParams;
347 }
348 else
349 {
350 bDone = true;
351 }
352 }
353
354 if (1 == iParams)
355 {
356 }
357 else if (2 == iParams)
358 {
359 if (!jvParseLedger(jvRequest, jvParams[1u].asString()))
360 return jvRequest;
361 }
362 else
363 {
364 std::int64_t const uLedgerMin = jvParams[1u].asInt();
365 std::int64_t const uLedgerMax = jvParams[2u].asInt();
366
367 if (uLedgerMax != -1 && uLedgerMax < uLedgerMin)
368 {
369 if (apiVersion_ == 1)
371 return rpcError(RpcNotSynced);
372 }
373
374 jvRequest[jss::ledger_index_min] = jvParams[1u].asInt();
375 jvRequest[jss::ledger_index_max] = jvParams[2u].asInt();
376
377 if (iParams >= 4)
378 jvRequest[jss::limit] = jvParams[3u].asInt();
379
380 if (iParams >= 5)
381 jvRequest[jss::offset] = jvParams[4u].asInt();
382 }
383
384 return jvRequest;
385 }
386
387 // book_offers <taker_pays> <taker_gets> [<taker> [<ledger> [<limit>
388 // [<proof> [<marker>]]]]] limit: 0 = no limit proof: 0 or 1
389 //
390 // Mnemonic: taker pays --> offer --> taker gets
392 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
394 {
396
397 json::Value jvTakerPays = jvParseCurrencyIssuer(jvParams[0u].asString());
398 json::Value jvTakerGets = jvParseCurrencyIssuer(jvParams[1u].asString());
399
400 if (isRpcError(jvTakerPays))
401 {
402 return jvTakerPays;
403 }
404
405 jvRequest[jss::taker_pays] = jvTakerPays;
406
407 if (isRpcError(jvTakerGets))
408 {
409 return jvTakerGets;
410 }
411
412 jvRequest[jss::taker_gets] = jvTakerGets;
413
414 if (jvParams.size() >= 3)
415 {
416 jvRequest[jss::issuer] = jvParams[2u].asString();
417 }
418
419 if (jvParams.size() >= 4 && !jvParseLedger(jvRequest, jvParams[3u].asString()))
420 return jvRequest;
421
422 if (jvParams.size() >= 5)
423 {
424 try
425 {
426 int const iLimit = jvParams[4u].asInt();
427
428 if (iLimit > 0)
429 jvRequest[jss::limit] = iLimit;
430 }
431 catch (std::exception const&)
432 {
433 return rpc::invalidFieldError(jss::limit);
434 }
435 }
436
437 if (jvParams.size() >= 6)
438 {
439 try
440 {
441 int const bProof = jvParams[5u].asInt();
442 if (bProof != 0)
443 jvRequest[jss::proof] = true;
444 }
445 catch (std::exception const&)
446 {
447 return rpc::invalidFieldError(jss::proof);
448 }
449 }
450
451 if (jvParams.size() == 7)
452 jvRequest[jss::marker] = jvParams[6u];
453
454 return jvRequest;
455 }
456
457 // can_delete [<ledgerid>|<ledgerhash>|now|always|never]
459 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
461 {
463
464 if (jvParams.size() == 0u)
465 return jvRequest;
466
467 std::string const input = jvParams[0u].asString();
468 if (input.find_first_not_of("0123456789") == std::string::npos)
469 {
470 jvRequest["can_delete"] = jvParams[0u].asUInt();
471 }
472 else
473 {
474 jvRequest["can_delete"] = input;
475 }
476
477 return jvRequest;
478 }
479
480 // connect <ip[:port]> [port]
482 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
483 parseConnect(json::Value const& jvParams)
484 {
486 std::string ip = jvParams[0u].asString();
487 if (jvParams.size() == 2)
488 {
489 jvRequest[jss::ip] = ip;
490 jvRequest[jss::port] = jvParams[1u].asUInt();
491 return jvRequest;
492 }
493
494 // handle case where there is one argument of the form ip:port
495 if (std::count(ip.begin(), ip.end(), ':') == 1)
496 {
497 std::size_t const colon = ip.find_last_of(':');
498 jvRequest[jss::ip] = std::string{ip, 0, colon};
499 jvRequest[jss::port] = json::Value{std::string{ip, colon + 1}}.asUInt();
500 return jvRequest;
501 }
502
503 // default case, no port
504 jvRequest[jss::ip] = ip;
505 return jvRequest;
506 }
507
508 // deposit_authorized <source_account> <destination_account>
509 // [<ledger> [<credentials>, ...]]
511 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
513 {
515 jvRequest[jss::source_account] = jvParams[0u].asString();
516 jvRequest[jss::destination_account] = jvParams[1u].asString();
517
518 if (jvParams.size() >= 3)
519 jvParseLedger(jvRequest, jvParams[2u].asString());
520
521 // 8 credentials max
522 if ((jvParams.size() >= 4) && (jvParams.size() <= 11))
523 {
524 jvRequest[jss::credentials] = json::Value(json::ValueType::Array);
525 for (uint32_t i = 3; i < jvParams.size(); ++i)
526 jvRequest[jss::credentials].append(jvParams[i].asString());
527 }
528
529 return jvRequest;
530 }
531
532 // Return an error for attempting to subscribe/unsubscribe via RPC.
534 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
535 parseEvented(json::Value const& jvParams)
536 {
537 return rpcError(RpcNoEvents);
538 }
539
540 // feature [<feature>] [accept|reject]
542 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
543 parseFeature(json::Value const& jvParams)
544 {
546
547 if (jvParams.size() > 0)
548 jvRequest[jss::feature] = jvParams[0u].asString();
549
550 if (jvParams.size() > 1)
551 {
552 auto const action = jvParams[1u].asString();
553
554 // This may look reversed, but it's intentional: jss::vetoed
555 // determines whether an amendment is vetoed - so "reject" means
556 // that jss::vetoed is true.
557 if (boost::iequals(action, "reject"))
558 {
559 jvRequest[jss::vetoed] = json::Value(true);
560 }
561 else if (boost::iequals(action, "accept"))
562 {
563 jvRequest[jss::vetoed] = json::Value(false);
564 }
565 else
566 {
568 }
569 }
570
571 return jvRequest;
572 }
573
574 // get_counts [<min_count>]
576 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
578 {
580
581 if (jvParams.size() != 0u)
582 jvRequest[jss::min_count] = jvParams[0u].asUInt();
583
584 return jvRequest;
585 }
586
587 // sign_for <account> <secret> <json> offline
588 // sign_for <account> <secret> <json>
590 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
591 parseSignFor(json::Value const& jvParams)
592 {
593 bool const bOffline = 4 == jvParams.size() && jvParams[3u].asString() == "offline";
594
595 if (3 == jvParams.size() || bOffline)
596 {
597 json::Value txJSON;
598 json::Reader reader;
599 if (reader.parse(jvParams[2u].asString(), txJSON))
600 {
601 // sign_for txJSON.
603
604 jvRequest[jss::account] = jvParams[0u].asString();
605 jvRequest[jss::secret] = jvParams[1u].asString();
606 jvRequest[jss::tx_json] = txJSON;
607
608 if (bOffline)
609 jvRequest[jss::offline] = true;
610
611 return jvRequest;
612 }
613 }
615 }
616
617 // json <command> <json>
619 parseJson(json::Value const& jvParams)
620 {
621 json::Reader reader;
622 json::Value jvRequest;
623
624 JLOG(j_.trace()) << "RPC method: " << jvParams[0u];
625 JLOG(j_.trace()) << "RPC json: " << jvParams[1u];
626
627 if (reader.parse(jvParams[1u].asString(), jvRequest))
628 {
629 if (!jvRequest.isObjectOrNull())
631
632 jvRequest[jss::method] = jvParams[0u];
633
634 return jvRequest;
635 }
636
638 }
639
640 bool
642 {
643 if (jv.isArray())
644 {
645 if (jv.size() == 0)
646 return false;
647 // json::Value is not a std::ranges range, so the iterator form is used.
648 // NOLINTNEXTLINE(modernize-use-ranges)
649 return std::all_of(
650 jv.begin(), jv.end(), [this](auto const& j) { return isValidJson2(j); });
651 }
652 if (jv.isObject())
653 {
654 if (jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0" &&
655 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0" &&
656 jv.isMember(jss::id) && jv.isMember(jss::method))
657 {
658 return !jv.isMember(jss::params) ||
659 (jv[jss::params].isNull() || jv[jss::params].isArray() ||
660 jv[jss::params].isObject());
661 }
662 }
663 return false;
664 }
665
667 parseJson2(json::Value const& jvParams)
668 {
669 json::Reader reader;
670 json::Value jv;
671 bool const validParse = reader.parse(jvParams[0u].asString(), jv);
672 if (validParse && isValidJson2(jv))
673 {
674 if (jv.isObject())
675 {
677 if (jv.isMember(jss::params))
678 {
679 auto const& params = jv[jss::params];
680 for (auto i = params.begin(); i != params.end(); ++i)
681 jv1[i.key().asString()] = *i;
682 }
683 jv1[jss::jsonrpc] = jv[jss::jsonrpc];
684 jv1[jss::ripplerpc] = jv[jss::ripplerpc];
685 jv1[jss::id] = jv[jss::id];
686 jv1[jss::method] = jv[jss::method];
687 return jv1;
688 }
689 // else jv.isArray()
691 for (json::UInt j = 0; j < jv.size(); ++j)
692 {
693 if (jv[j].isMember(jss::params))
694 {
695 auto const& params = jv[j][jss::params];
696 for (auto i = params.begin(); i != params.end(); ++i)
697 jv1[j][i.key().asString()] = *i;
698 }
699 jv1[j][jss::jsonrpc] = jv[j][jss::jsonrpc];
700 jv1[j][jss::ripplerpc] = jv[j][jss::ripplerpc];
701 jv1[j][jss::id] = jv[j][jss::id];
702 jv1[j][jss::method] = jv[j][jss::method];
703 }
704 return jv1;
705 }
706 auto jvError = rpcError(RpcInvalidParams);
707 if (jv.isMember(jss::jsonrpc))
708 jvError[jss::jsonrpc] = jv[jss::jsonrpc];
709 if (jv.isMember(jss::ripplerpc))
710 jvError[jss::ripplerpc] = jv[jss::ripplerpc];
711 if (jv.isMember(jss::id))
712 jvError[jss::id] = jv[jss::id];
713 return jvError;
714 }
715
716 // ledger [id|index|current|closed|validated] [full|tx]
718 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
719 parseLedger(json::Value const& jvParams)
720 {
722
723 if (jvParams.size() == 0u)
724 {
725 return jvRequest;
726 }
727
728 jvParseLedger(jvRequest, jvParams[0u].asString());
729
730 if (2 == jvParams.size())
731 {
732 if (jvParams[1u].asString() == "full")
733 {
734 jvRequest[jss::full] = true;
735 }
736 else if (jvParams[1u].asString() == "tx")
737 {
738 jvRequest[jss::transactions] = true;
739 jvRequest[jss::expand] = true;
740 }
741 }
742
743 return jvRequest;
744 }
745
746 // ledger_header <id>|<index>
748 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
749 parseLedgerId(json::Value const& jvParams)
750 {
752
753 std::string const strLedger = jvParams[0u].asString();
754
755 if (strLedger.length() == 64)
756 {
757 jvRequest[jss::ledger_hash] = strLedger;
758 }
759 else
760 {
761 jvRequest[jss::ledger_index] = beast::lexicalCast<std::uint32_t>(strLedger);
762 }
763
764 return jvRequest;
765 }
766
767 // ledger_entry [id] [<index>]
769 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
771 {
773
774 jvRequest[jss::index] = jvParams[0u].asString();
775
776 if (jvParams.size() == 2 && !jvParseLedger(jvRequest, jvParams[1u].asString()))
778
779 return jvRequest;
780 }
781
782 // log_level: Get log levels
783 // log_level <severity>: Set master log level to the
784 // specified severity log_level <partition> <severity>: Set specified
785 // partition to specified severity
787 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
788 parseLogLevel(json::Value const& jvParams)
789 {
791
792 if (jvParams.size() == 1)
793 {
794 jvRequest[jss::severity] = jvParams[0u].asString();
795 }
796 else if (jvParams.size() == 2)
797 {
798 jvRequest[jss::partition] = jvParams[0u].asString();
799 jvRequest[jss::severity] = jvParams[1u].asString();
800 }
801
802 return jvRequest;
803 }
804
805 // owner_info <account>
806 // account_info <account> [<ledger>]
807 // account_offers <account> [<ledger>]
810 {
811 return parseAccountRaw1(jvParams);
812 }
813
816 {
817 return parseAccountRaw1(jvParams);
818 }
819
820 // account_lines <account> <account>|"" [<ledger>]
823 {
824 return parseAccountRaw2(jvParams, jss::peer);
825 }
826
827 // account_channels <account> <account>|"" [<ledger>]
830 {
831 return parseAccountRaw2(jvParams, jss::destination_account);
832 }
833
834 // channel_authorize: <private_key> [<key_type>] <channel_id> <drops>
836 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
838 {
840
841 unsigned int index = 0;
842
843 if (jvParams.size() == 4)
844 {
845 jvRequest[jss::passphrase] = jvParams[index];
846 index++;
847
848 if (!keyTypeFromString(jvParams[index].asString()))
849 return rpcError(RpcBadKeyType);
850 jvRequest[jss::key_type] = jvParams[index];
851 index++;
852 }
853 else
854 {
855 jvRequest[jss::secret] = jvParams[index];
856 index++;
857 }
858
859 {
860 // verify the channel id is a valid 256 bit number
861 UInt256 channelId;
862 if (!channelId.parseHex(jvParams[index].asString()))
864 jvRequest[jss::channel_id] = to_string(channelId);
865 index++;
866 }
867
868 if (!jvParams[index].isString() || !toUInt64(jvParams[index].asString()))
870 jvRequest[jss::amount] = jvParams[index];
871
872 // If additional parameters are appended, be sure to increment index
873 // here
874
875 return jvRequest;
876 }
877
878 // channel_verify <public_key> <channel_id> <drops> <signature>
880 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
882 {
883 std::string const strPk = jvParams[0u].asString();
884
885 if (!validPublicKey(strPk))
887
889
890 jvRequest[jss::public_key] = strPk;
891 {
892 // verify the channel id is a valid 256 bit number
893 UInt256 channelId;
894 if (!channelId.parseHex(jvParams[1u].asString()))
896 }
897 jvRequest[jss::channel_id] = jvParams[1u].asString();
898
899 if (!jvParams[2u].isString() || !toUInt64(jvParams[2u].asString()))
901 jvRequest[jss::amount] = jvParams[2u];
902
903 jvRequest[jss::signature] = jvParams[3u].asString();
904
905 return jvRequest;
906 }
907
909 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
910 parseAccountRaw2(json::Value const& jvParams, char const* const acc2Field)
911 {
912 std::array<char const* const, 2> accFields{{jss::account, acc2Field}};
913 auto const nParams = jvParams.size();
915 for (auto i = 0; i < nParams; ++i)
916 {
917 // This was non-const. see comment below
918 std::string const strParam = jvParams[i].asString();
919
920 if (i == 1 && strParam.empty())
921 continue;
922
923 // Parameters 0 and 1 are accounts
924 if (i < 2)
925 {
926 if (parseBase58<AccountID>(strParam))
927 {
928 // TODO: this was std::move'd before but it does not work in practice.
929 // We would need a Value(std::string&&) for it to work.
930 // See https://github.com/XRPLF/rippled/issues/6677
931 jvRequest[accFields[i]] = strParam;
932 }
933 else
934 {
936 }
937 }
938 else
939 {
940 if (jvParseLedger(jvRequest, strParam))
941 return jvRequest;
943 }
944 }
945
946 return jvRequest;
947 }
948
949 // TODO: Get index from an alternate syntax: rXYZ:<index>
951 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
953 {
954 std::string const strIdent = jvParams[0u].asString();
955 unsigned int const iCursor = jvParams.size();
956
957 if (!parseBase58<AccountID>(strIdent))
959
960 // Get info on account.
962
963 jvRequest[jss::account] = strIdent;
964
965 if (iCursor == 2 && !jvParseLedger(jvRequest, jvParams[1u].asString()))
967
968 return jvRequest;
969 }
970
972 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
973 parseVault(json::Value const& jvParams)
974 {
975 std::string const strVaultID = jvParams[0u].asString();
977 if (!id.parseHex(strVaultID))
979
981 jvRequest[jss::vault_id] = strVaultID;
982
983 if (jvParams.size() > 1)
984 jvParseLedger(jvRequest, jvParams[1u].asString());
985
986 return jvRequest;
987 }
988
989 // peer_reservations_add <public_key> [<name>]
991 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
993 {
994 json::Value jvRequest;
995 jvRequest[jss::public_key] = jvParams[0u].asString();
996 if (jvParams.size() > 1)
997 {
998 jvRequest[jss::description] = jvParams[1u].asString();
999 }
1000 return jvRequest;
1001 }
1002
1003 // peer_reservations_del <public_key>
1005 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
1007 {
1008 json::Value jvRequest;
1009 jvRequest[jss::public_key] = jvParams[0u].asString();
1010 return jvRequest;
1011 }
1012
1013 // ripple_path_find <json> [<ledger>]
1016 {
1017 json::Reader reader;
1019 bool const bLedger = 2 == jvParams.size();
1020
1021 JLOG(j_.trace()) << "RPC json: " << jvParams[0u];
1022
1023 if (reader.parse(jvParams[0u].asString(), jvRequest))
1024 {
1025 if (bLedger)
1026 {
1027 jvParseLedger(jvRequest, jvParams[1u].asString());
1028 }
1029
1030 return jvRequest;
1031 }
1032
1033 return rpcError(RpcInvalidParams);
1034 }
1035
1036 // simulate any transaction on the network
1037 //
1038 // simulate <tx_blob> [binary]
1039 // simulate <tx_json> [binary]
1041 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
1043 {
1044 json::Value txJSON;
1045 json::Reader reader;
1047
1048 if (reader.parse(jvParams[0u].asString(), txJSON))
1049 {
1050 jvRequest[jss::tx_json] = txJSON;
1051 }
1052 else
1053 {
1054 jvRequest[jss::tx_blob] = jvParams[0u].asString();
1055 }
1056
1057 if (jvParams.size() == 2)
1058 {
1059 if (!jvParams[1u].isString() || jvParams[1u].asString() != "binary")
1060 return rpcError(RpcInvalidParams);
1061 jvRequest[jss::binary] = true;
1062 }
1063
1064 return jvRequest;
1065 }
1066
1067 // sign/submit any transaction to the network
1068 //
1069 // sign <private_key> <json> offline
1070 // submit <private_key> <json>
1071 // submit <tx_blob>
1073 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
1075 {
1076 json::Value txJSON;
1077 json::Reader reader;
1078 bool const bOffline = jvParams.size() >= 3 && jvParams[2u].asString() == "offline";
1079 std::optional<std::string> const field = [&jvParams,
1080 bOffline]() -> std::optional<std::string> {
1081 if (jvParams.size() < 3)
1082 return std::nullopt;
1083 if (jvParams.size() < 4 && bOffline)
1084 return std::nullopt;
1085 json::UInt const index = bOffline ? 3u : 2u;
1086 return jvParams[index].asString();
1087 }();
1088
1089 if (1 == jvParams.size())
1090 {
1091 // Submitting tx_blob
1092
1094
1095 jvRequest[jss::tx_blob] = jvParams[0u].asString();
1096
1097 return jvRequest;
1098 }
1099 if ((jvParams.size() >= 2 || bOffline) && reader.parse(jvParams[1u].asString(), txJSON))
1100 {
1101 // Signing or submitting tx_json.
1103
1104 jvRequest[jss::secret] = jvParams[0u].asString();
1105 jvRequest[jss::tx_json] = txJSON;
1106
1107 if (bOffline)
1108 jvRequest[jss::offline] = true;
1109
1110 if (field)
1111 jvRequest[jss::signature_target] = *field;
1112
1113 return jvRequest;
1114 }
1115
1116 return rpcError(RpcInvalidParams);
1117 }
1118
1119 // submit any multisigned transaction to the network
1120 //
1121 // submit_multisigned <json>
1123 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
1125 {
1126 if (1 == jvParams.size())
1127 {
1128 json::Value txJSON;
1129 json::Reader reader;
1130 if (reader.parse(jvParams[0u].asString(), txJSON))
1131 {
1133 jvRequest[jss::tx_json] = txJSON;
1134 return jvRequest;
1135 }
1136 }
1137
1138 return rpcError(RpcInvalidParams);
1139 }
1140
1141 // transaction_entry <tx_hash> <ledger_hash/ledger_index>
1143 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
1145 {
1146 // Parameter count should have already been verified.
1147 XRPL_ASSERT(
1148 jvParams.size() == 2, "xrpl::RPCParser::parseTransactionEntry : valid parameter count");
1149
1150 std::string const txHash = jvParams[0u].asString();
1151 if (txHash.length() != 64)
1152 return rpcError(RpcInvalidParams);
1153
1155 jvRequest[jss::tx_hash] = txHash;
1156
1157 jvParseLedger(jvRequest, jvParams[1u].asString());
1158
1159 // jvParseLedger inserts a "ledger_index" of 0 if it doesn't
1160 // find a match.
1161 if (jvRequest.isMember(jss::ledger_index) && jvRequest[jss::ledger_index] == 0)
1162 return rpcError(RpcInvalidParams);
1163
1164 return jvRequest;
1165 }
1166
1167 // tx <transaction_id>
1169 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
1170 parseTx(json::Value const& jvParams)
1171 {
1173
1174 if (jvParams.size() == 2 || jvParams.size() == 4)
1175 {
1176 if (jvParams[1u].asString() == jss::binary)
1177 jvRequest[jss::binary] = true;
1178 }
1179
1180 if (jvParams.size() >= 3)
1181 {
1182 auto const offset = jvParams.size() == 3 ? 0 : 1;
1183
1184 jvRequest[jss::min_ledger] = jvParams[1u + offset].asString();
1185 jvRequest[jss::max_ledger] = jvParams[2u + offset].asString();
1186 }
1187
1188 if (jvParams[0u].asString().length() == 16)
1189 {
1190 jvRequest[jss::ctid] = jvParams[0u].asString();
1191 }
1192 else
1193 {
1194 jvRequest[jss::transaction] = jvParams[0u].asString();
1195 }
1196
1197 return jvRequest;
1198 }
1199
1200 // tx_history <index>
1202 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
1204 {
1206
1207 jvRequest[jss::start] = jvParams[0u].asUInt();
1208
1209 return jvRequest;
1210 }
1211
1212 // validation_create [<pass_phrase>|<seed>|<seed_key>]
1213 //
1214 // NOTE: It is poor security to specify secret information on the command
1215 // line. This information might be saved in the command shell history file
1216 // (e.g. .bash_history) and it may be leaked via the process status command
1217 // (i.e. ps).
1219 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
1221 {
1223
1224 if (jvParams.size() != 0u)
1225 jvRequest[jss::secret] = jvParams[0u].asString();
1226
1227 return jvRequest;
1228 }
1229
1230 // wallet_propose [<passphrase>]
1231 // <passphrase> is only for testing. Master seeds should only be generated
1232 // randomly.
1234 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
1236 {
1238
1239 if (jvParams.size() != 0u)
1240 jvRequest[jss::passphrase] = jvParams[0u].asString();
1241
1242 return jvRequest;
1243 }
1244
1245 // parse gateway balances
1246 // gateway_balances [<ledger>] <issuer_account> [ <hotwallet> [ <hotwallet>
1247 // ]]
1248
1250 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
1252 {
1253 unsigned int index = 0;
1254 unsigned int const size = jvParams.size();
1255
1257
1258 std::string param = jvParams[index++].asString();
1259 if (param.empty())
1260 return rpc::makeParamError("Invalid first parameter");
1261
1262 if (param[0] != 'r')
1263 {
1264 if (param.size() == 64)
1265 {
1266 jvRequest[jss::ledger_hash] = param;
1267 }
1268 else
1269 {
1270 jvRequest[jss::ledger_index] = param;
1271 }
1272
1273 if (size <= index)
1274 return rpc::makeParamError("Invalid hotwallet");
1275
1276 param = jvParams[index++].asString();
1277 }
1278
1279 jvRequest[jss::account] = param;
1280
1281 if (index < size)
1282 {
1283 json::Value& hotWallets = (jvRequest["hotwallet"] = json::ValueType::Array);
1284 while (index < size)
1285 hotWallets.append(jvParams[index++].asString());
1286 }
1287
1288 return jvRequest;
1289 }
1290
1291 // server_definitions [hash]
1293 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
1295 {
1297
1298 if (jvParams.size() == 1)
1299 {
1300 jvRequest[jss::hash] = jvParams[0u].asString();
1301 }
1302
1303 return jvRequest;
1304 }
1305
1306 // server_info [counters]
1308 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
1310 {
1312 if (jvParams.size() == 1 && jvParams[0u].asString() == "counters")
1313 jvRequest[jss::counters] = true;
1314 return jvRequest;
1315 }
1316
1317 // An omitted minParams means the command takes no arguments; an omitted
1318 // maxParams means it takes any number. See Command.
1319 //
1320 // The commands. The order is free: parseCommand() searches kSortedCommands
1321 // below.
1322 static constexpr auto kCommandArray = std::to_array<Command>({
1323 // Request-response methods
1324 // - Returns an error, or the request.
1325 // - To modify the method, provide a new method in the request.
1326 {
1328 .parse = Parse::of<&RPCParser::parseAccountCurrencies>(),
1329 .minParams = 1,
1330 .maxParams = 3,
1331 },
1332 {
1334 .parse = Parse::of<&RPCParser::parseAccountItems>(),
1335 .minParams = 1,
1336 .maxParams = 3,
1337 },
1338 {
1340 .parse = Parse::of<&RPCParser::parseAccountLines>(),
1341 .minParams = 1,
1342 .maxParams = 5,
1343 },
1344 {
1346 .parse = Parse::of<&RPCParser::parseAccountChannels>(),
1347 .minParams = 1,
1348 .maxParams = 3,
1349 },
1350 {
1352 .parse = Parse::of<&RPCParser::parseAccountItems>(),
1353 .minParams = 1,
1354 .maxParams = 5,
1355 },
1356 {
1358 .parse = Parse::of<&RPCParser::parseAccountItems>(),
1359 .minParams = 1,
1360 .maxParams = 5,
1361 },
1362 {
1364 .parse = Parse::of<&RPCParser::parseAccountItems>(),
1365 .minParams = 1,
1366 .maxParams = 4,
1367 },
1368 {
1370 .parse = Parse::of<&RPCParser::parseAccountTransactions>(),
1371 .minParams = 1,
1372 .maxParams = 8,
1373 },
1374 {
1375 .name = rpc::method::kAmmInfo,
1376 .parse = Parse::of<&RPCParser::parseAsIs>(),
1377 .minParams = 1,
1378 .maxParams = 2,
1379 },
1380 {
1382 .parse = Parse::of<&RPCParser::parseVault>(),
1383 .minParams = 1,
1384 .maxParams = 2,
1385 },
1386 {
1388 .parse = Parse::of<&RPCParser::parseLedgerId>(),
1389 .minParams = 1,
1390 .maxParams = 1,
1391 },
1392 {
1394 .parse = Parse::of<&RPCParser::parseBookOffers>(),
1395 .minParams = 2,
1396 .maxParams = 7,
1397 },
1398 {
1400 .parse = Parse::of<&RPCParser::parseCanDelete>(),
1401 .maxParams = 1,
1402 },
1403 {
1405 .parse = Parse::of<&RPCParser::parseChannelAuthorize>(),
1406 .minParams = 3,
1407 .maxParams = 4,
1408 },
1409 {
1411 .parse = Parse::of<&RPCParser::parseChannelVerify>(),
1412 .minParams = 4,
1413 .maxParams = 4,
1414 },
1415 {
1416 .name = rpc::method::kConnect,
1417 .parse = Parse::of<&RPCParser::parseConnect>(),
1418 .minParams = 1,
1419 .maxParams = 2,
1420 },
1421 {
1423 .parse = Parse::of<&RPCParser::parseAsIs>(),
1424 .maxParams = 0,
1425 },
1426 {
1428 .parse = Parse::of<&RPCParser::parseDepositAuthorized>(),
1429 .minParams = 2,
1430 .maxParams = 11,
1431 },
1432 {
1433 .name = rpc::method::kFeature,
1434 .parse = Parse::of<&RPCParser::parseFeature>(),
1435 .maxParams = 2,
1436 },
1437 {
1439 .parse = Parse::of<&RPCParser::parseFetchInfo>(),
1440 .maxParams = 1,
1441 },
1442 {
1444 .parse = Parse::of<&RPCParser::parseGatewayBalances>(),
1445 .minParams = 1,
1446 },
1447 {
1449 .parse = Parse::of<&RPCParser::parseGetCounts>(),
1450 .maxParams = 1,
1451 },
1452 {
1453 .name = rpc::method::kJson,
1454 .parse = Parse::of<&RPCParser::parseJson>(),
1455 .minParams = 2,
1456 .maxParams = 2,
1457 },
1458 {
1459 .name = rpc::method::kJson2,
1460 .parse = Parse::of<&RPCParser::parseJson2>(),
1461 .minParams = 1,
1462 .maxParams = 1,
1463 },
1464 {
1465 .name = rpc::method::kLedger,
1466 .parse = Parse::of<&RPCParser::parseLedger>(),
1467 .maxParams = 2,
1468 },
1469 {
1471 .parse = Parse::of<&RPCParser::parseAsIs>(),
1472 .maxParams = 0,
1473 },
1474 {
1476 .parse = Parse::of<&RPCParser::parseAsIs>(),
1477 .maxParams = 0,
1478 },
1479 {
1481 .parse = Parse::of<&RPCParser::parseAsIs>(),
1482 .maxParams = 0,
1483 },
1484 {
1486 .parse = Parse::of<&RPCParser::parseLedgerEntry>(),
1487 .minParams = 1,
1488 .maxParams = 2,
1489 },
1490 {
1492 .parse = Parse::of<&RPCParser::parseLedgerId>(),
1493 .minParams = 1,
1494 .maxParams = 1,
1495 },
1496 {
1498 .parse = Parse::of<&RPCParser::parseLedgerId>(),
1499 .minParams = 1,
1500 .maxParams = 1,
1501 },
1502 {
1503 .name = rpc::method::kLogLevel,
1504 .parse = Parse::of<&RPCParser::parseLogLevel>(),
1505 .maxParams = 2,
1506 },
1507 {
1509 .parse = Parse::of<&RPCParser::parseAsIs>(),
1510 .maxParams = 0,
1511 },
1512 {
1513 .name = rpc::method::kManifest,
1514 .parse = Parse::of<&RPCParser::parseManifest>(),
1515 .minParams = 1,
1516 .maxParams = 1,
1517 },
1518 {
1520 .parse = Parse::of<&RPCParser::parseAccountItems>(),
1521 .minParams = 1,
1522 .maxParams = 3,
1523 },
1524 {
1525 .name = rpc::method::kPeers,
1526 .parse = Parse::of<&RPCParser::parseAsIs>(),
1527 .maxParams = 0,
1528 },
1529 {
1530 .name = rpc::method::kPing,
1531 .parse = Parse::of<&RPCParser::parseAsIs>(),
1532 .maxParams = 0,
1533 },
1534 {
1535 .name = rpc::method::kPrint,
1536 .parse = Parse::of<&RPCParser::parseAsIs>(),
1537 .maxParams = 1,
1538 },
1539 {
1540 .name = rpc::method::kRandom,
1541 .parse = Parse::of<&RPCParser::parseAsIs>(),
1542 .maxParams = 0,
1543 },
1544 {
1546 .parse = Parse::of<&RPCParser::parsePeerReservationsAdd>(),
1547 .minParams = 1,
1548 .maxParams = 2,
1549 },
1550 {
1552 .parse = Parse::of<&RPCParser::parsePeerReservationsDel>(),
1553 .minParams = 1,
1554 .maxParams = 1,
1555 },
1556 {
1558 .parse = Parse::of<&RPCParser::parseAsIs>(),
1559 .maxParams = 0,
1560 },
1561 {
1563 .parse = Parse::of<&RPCParser::parseRipplePathFind>(),
1564 .minParams = 1,
1565 .maxParams = 2,
1566 },
1567 {
1569 .parse = Parse::of<&RPCParser::parseServerDefinitions>(),
1570 .maxParams = 1,
1571 },
1572 {
1574 .parse = Parse::of<&RPCParser::parseServerInfo>(),
1575 .maxParams = 1,
1576 },
1577 {
1579 .parse = Parse::of<&RPCParser::parseServerInfo>(),
1580 .maxParams = 1,
1581 },
1582 {
1583 .name = rpc::method::kSign,
1584 .parse = Parse::of<&RPCParser::parseSignSubmit>(),
1585 .minParams = 2,
1586 .maxParams = 4,
1587 },
1588 {
1589 .name = rpc::method::kSignFor,
1590 .parse = Parse::of<&RPCParser::parseSignFor>(),
1591 .minParams = 3,
1592 .maxParams = 4,
1593 },
1594 {
1595 .name = rpc::method::kStop,
1596 .parse = Parse::of<&RPCParser::parseAsIs>(),
1597 .maxParams = 0,
1598 },
1599 {
1600 .name = rpc::method::kSimulate,
1601 .parse = Parse::of<&RPCParser::parseSimulate>(),
1602 .minParams = 1,
1603 .maxParams = 2,
1604 },
1605 {
1606 .name = rpc::method::kSubmit,
1607 .parse = Parse::of<&RPCParser::parseSignSubmit>(),
1608 .minParams = 1,
1609 .maxParams = 4,
1610 },
1611 {
1613 .parse = Parse::of<&RPCParser::parseSubmitMultiSigned>(),
1614 .minParams = 1,
1615 .maxParams = 1,
1616 },
1617 {
1619 .parse = Parse::of<&RPCParser::parseTransactionEntry>(),
1620 .minParams = 2,
1621 .maxParams = 2,
1622 },
1623 {
1624 .name = rpc::method::kTx,
1625 .parse = Parse::of<&RPCParser::parseTx>(),
1626 .minParams = 1,
1627 .maxParams = 4,
1628 },
1629 {
1631 .parse = Parse::of<&RPCParser::parseTxHistory>(),
1632 .minParams = 1,
1633 .maxParams = 1,
1634 },
1635 {
1636 .name = rpc::method::kUnlList,
1637 .parse = Parse::of<&RPCParser::parseAsIs>(),
1638 .maxParams = 0,
1639 },
1640 {
1642 .parse = Parse::of<&RPCParser::parseValidationCreate>(),
1643 .maxParams = 1,
1644 },
1645 {
1647 .parse = Parse::of<&RPCParser::parseAsIs>(),
1648 .maxParams = 0,
1649 },
1650 {
1651 .name = rpc::method::kVersion,
1652 .parse = Parse::of<&RPCParser::parseAsIs>(),
1653 .maxParams = 0,
1654 },
1655 {
1657 .parse = Parse::of<&RPCParser::parseWalletPropose>(),
1658 .maxParams = 1,
1659 },
1660 {
1661 .name = rpc::method::kInternal,
1662 .parse = Parse::of<&RPCParser::parseInternal>(),
1663 .minParams = 1,
1664 },
1665
1666 // Event methods, rejected below, so the parameter range is unconstrained
1667 {
1668 .name = rpc::method::kPathFind,
1669 .parse = Parse::of<&RPCParser::parseEvented>(),
1670 },
1671 {
1673 .parse = Parse::of<&RPCParser::parseEvented>(),
1674 },
1675 {
1677 .parse = Parse::of<&RPCParser::parseEvented>(),
1678 },
1679 });
1680
1681 // kCommandArray sorted by name, so a command can be found by binary search.
1682 static constexpr auto kSortedCommands = [] {
1683 auto commands = kCommandArray;
1684 std::ranges::sort(commands, {}, &Command::name);
1685 return commands;
1686 }();
1687
1688 // parseCommand() relies on this being sorted to binary search it, and
1689 // kCommandNames below inherits the order.
1690 static_assert(
1691 std::ranges::is_sorted(kSortedCommands, {}, &Command::name),
1692 "xrpl::RPCParser : kSortedCommands must be sorted");
1693
1694 // The command names, which are already distinct and sorted.
1695 static constexpr auto kCommandNames = [] {
1697 std::ranges::transform(kSortedCommands, names.begin(), &Command::name);
1698 return names;
1699 }();
1700
1701public:
1707 {
1708 return kCommandNames;
1709 }
1710
1726 static constexpr bool
1728 {
1729 for (std::size_t i = 0; i < kSortedCommands.size(); ++i)
1730 {
1731 auto const& command = kSortedCommands[i];
1732 if (command.name.empty() || command.minParams > command.maxParams)
1733 return false;
1734 if (i > 0 && kSortedCommands[i - 1].name == command.name)
1735 return false;
1736 }
1737 return true;
1738 }
1739
1740 //--------------------------------------------------------------------------
1741
1742 explicit RPCParser(unsigned apiVersion, beast::Journal j) : apiVersion_(apiVersion), j_(j)
1743 {
1744 }
1745
1746 //--------------------------------------------------------------------------
1747
1748 // Convert a rpc method and params to a request.
1749 // <-- { method: xyz, params: [... ] } or { error: ..., ... }
1751 parseCommand(std::string_view strMethod, json::Value const& jvParams, bool allowAnyCommand)
1752 {
1753 if (auto stream = j_.trace())
1754 {
1755 stream << "Method: '" << strMethod << "'";
1756 stream << "Params: " << jvParams;
1757 }
1758
1759 auto const found = std::ranges::lower_bound(kSortedCommands, strMethod, {}, &Command::name);
1760
1761 if (found == kSortedCommands.end() || found->name != strMethod)
1762 {
1763 // The command could not be found
1764 if (!allowAnyCommand)
1766
1767 return parseAsIs(jvParams);
1768 }
1769
1770 auto const count = jvParams.size();
1771 if (count < found->minParams || count > found->maxParams)
1772 {
1773 JLOG(j_.debug()) << "Wrong number of parameters for " << found->name
1774 << " minimum=" << found->minParams << " maximum=" << found->maxParams
1775 << " actual=" << count;
1776
1777 return rpcError(RpcBadSyntax);
1778 }
1779
1780 return found->parse(*this, jvParams);
1781 }
1782};
1783
1784namespace {
1785
1786// Out of line because RPCParser is incomplete where Parse is declared.
1788Parse::operator()(RPCParser& parser, json::Value const& jvParams) const
1789{
1790 return (parser.*fn_)(jvParams);
1791}
1792
1793} // namespace
1794
1795// See the comment on commandsValid() for why this is out here.
1796static_assert(
1798 "xrpl::RPCParser : every command needs a unique name and a valid parameter "
1799 "count range");
1800
1801//------------------------------------------------------------------------------
1802
1803//
1804// JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1805// but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1806// unspecified (HTTP errors and contents of 'error').
1807//
1808// 1.0 spec: http://json-rpc.org/wiki/specification
1809// 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1810//
1811
1812std::string
1813jsonrpcRequest(std::string const& strMethod, json::Value const& params, json::Value const& id)
1814{
1815 json::Value request;
1816 request[jss::method] = strMethod;
1817 request[jss::params] = params;
1818 request[jss::id] = id;
1819 return to_string(request) + "\n";
1820}
1821
1822namespace {
1823// Special local exception type thrown when request can't be parsed.
1824class RequestNotParsable : public std::runtime_error
1825{
1826 using std::runtime_error::runtime_error; // Inherit constructors
1827};
1828}; // namespace
1829
1831{
1832 explicit RPCCallImp() = default;
1833
1834 // VFALCO NOTE Is this a to-do comment or a doc comment?
1835 // Place the async result somewhere useful.
1836 static void
1837 callRPCHandler(json::Value* jvOutput, json::Value const& jvInput)
1838 {
1839 (*jvOutput) = jvInput;
1840 }
1841
1842 static bool
1844 std::function<void(json::Value const& jvInput)> callbackFuncP,
1845 boost::system::error_code const& ecResult,
1846 int iStatus,
1847 std::string const& strData,
1849 {
1850 if (callbackFuncP)
1851 {
1852 // Only care about the result, if we care to deliver it
1853 // callbackFuncP.
1854
1855 // Receive reply
1856 if (strData.empty())
1857 {
1859 "no response from server. Please "
1860 "ensure that the xrpld server is running in another "
1861 "process.");
1862 }
1863
1864 // Parse reply
1865 JLOG(j.debug()) << "RPC reply: " << strData << std::endl;
1866 if (strData.starts_with("Unable to parse request") ||
1867 strData.starts_with(jss::invalid_API_version.cStr()))
1869 json::Reader reader;
1870 json::Value jvReply;
1871 if (!reader.parse(strData, jvReply))
1872 Throw<std::runtime_error>("couldn't parse reply from server");
1873
1874 if (!jvReply)
1875 Throw<std::runtime_error>("expected reply to have result, error and id properties");
1876
1878
1879 jvResult["result"] = jvReply;
1880
1881 callbackFuncP(jvResult);
1882 }
1883
1884 return false;
1885 }
1886
1887 // Build the request.
1888 static void
1890 std::string const& strMethod,
1891 json::Value const& jvParams,
1893 std::string const& strPath,
1894 boost::asio::streambuf& sb,
1895 std::string const& strHost,
1897 {
1898 JLOG(j.debug()) << "requestRPC: strPath='" << strPath << "'";
1899
1900 std::ostream osRequest(&sb);
1901 osRequest << createHTTPPost(
1902 strHost, strPath, jsonrpcRequest(strMethod, jvParams, json::Value(1)), headers);
1903 }
1904};
1905
1906//------------------------------------------------------------------------------
1907
1913
1914// Used internally by rpcClient.
1917 std::vector<std::string> const& args,
1918 json::Value& retParams,
1919 unsigned int apiVersion,
1921{
1923
1924 RPCParser rpParser(apiVersion, j);
1926
1927 for (int i = 1; i != args.size(); i++)
1928 jvRpcParams.append(args[i]);
1929
1931
1932 retParams[jss::method] = args[0];
1933 retParams[jss::params] = jvRpcParams;
1934
1935 jvRequest = rpParser.parseCommand(args[0], jvRpcParams, true);
1936
1937 auto insertApiVersion = [apiVersion](json::Value& jr) {
1938 if (jr.isObject() && !jr.isMember(jss::error) && !jr.isMember(jss::api_version))
1939 {
1940 jr[jss::api_version] = apiVersion;
1941 }
1942 };
1943
1944 if (jvRequest.isObject())
1945 {
1946 insertApiVersion(jvRequest);
1947 }
1948 else if (jvRequest.isArray())
1949 {
1950 // NOLINTNEXTLINE(modernize-use-ranges)
1951 std::for_each(jvRequest.begin(), jvRequest.end(), insertApiVersion);
1952 }
1953
1954 JLOG(j.trace()) << "RPC Request: " << jvRequest << std::endl;
1955 return jvRequest;
1956}
1957
1958//------------------------------------------------------------------------------
1959
1962 std::vector<std::string> const& args,
1963 Config const& config,
1964 Logs& logs,
1965 unsigned int apiVersion,
1967{
1968 static_assert(RpcBadSyntax == 1 && RpcSuccess == 0, "Expect specific rpc enum values.");
1969 if (args.empty())
1970 return {RpcBadSyntax, {}}; // rpcBAD_SYNTAX = print usage
1971
1972 int nRet = RpcSuccess;
1973 json::Value jvOutput;
1975
1976 try
1977 {
1979 jvRequest = rpcCmdToJson(args, jvRpc, apiVersion, logs.journal("RPCParser"));
1980
1981 if (jvRequest.isMember(jss::error))
1982 {
1983 jvOutput = jvRequest;
1984 jvOutput["rpc"] = jvRpc;
1985 }
1986 else
1987 {
1989 try
1990 {
1991 beast::LogStream rpcCallLog{logs.journal("HTTPClient").warn()};
1992 setup = setupServerHandler(config, rpcCallLog);
1993 }
1994 catch (std::exception const&) // NOLINT(bugprone-empty-catch)
1995 {
1996 // ignore any exceptions, so the command
1997 // line client works without a config file
1998 }
1999
2000 if (config.rpcIp)
2001 {
2002 setup.client.ip = config.rpcIp->address().to_string();
2003 setup.client.port = config.rpcIp->port();
2004 }
2005
2007
2008 if (!setup.client.adminUser.empty())
2009 jvRequest["admin_user"] = setup.client.adminUser;
2010
2011 if (!setup.client.adminPassword.empty())
2012 jvRequest["admin_password"] = setup.client.adminPassword;
2013
2014 if (jvRequest.isObject())
2015 {
2016 jvParams.append(jvRequest);
2017 }
2018 else if (jvRequest.isArray())
2019 {
2020 for (json::UInt i = 0; i < jvRequest.size(); ++i)
2021 jvParams.append(jvRequest[i]);
2022 }
2023
2024 {
2025 boost::asio::io_context isService;
2027 isService,
2028 setup.client.ip,
2029 setup.client.port,
2030 setup.client.user,
2031 setup.client.password,
2032 "",
2033 // Allow parser to rewrite method.
2034 [&]() -> std::string {
2035 if (jvRequest.isMember(jss::method))
2036 return jvRequest[jss::method].asString();
2037 return jvRequest.isArray() ? "batch" : args[0];
2038 }(),
2039 jvParams, // Parsed, execute.
2040 static_cast<int>(setup.client.secure) != 0, // Use SSL
2041 config.quiet(),
2042 logs,
2043 [&jvOutput](json::Value const& jvInput) {
2044 RPCCallImp::callRPCHandler(&jvOutput, jvInput);
2045 },
2046 headers);
2047 isService.run(); // This blocks until there are no more
2048 // outstanding async calls.
2049 }
2050 if (jvOutput.isMember("result"))
2051 {
2052 // Had a successful JSON-RPC 2.0 call.
2053 jvOutput = jvOutput["result"];
2054
2055 // jvOutput may report a server side error.
2056 // It should report "status".
2057 }
2058 else
2059 {
2060 // Transport error.
2061 json::Value const jvRpcError = jvOutput;
2062
2063 jvOutput = rpcError(RpcJsonRpc);
2064 jvOutput["result"] = jvRpcError;
2065 }
2066
2067 // If had an error, supply invocation in result.
2068 if (jvOutput.isMember(jss::error))
2069 {
2070 jvOutput["rpc"] = jvRpc; // How the command was seen as method + params.
2071 jvOutput["request_sent"] = jvRequest; // How the command was translated.
2072 }
2073 }
2074
2075 if (jvOutput.isMember(jss::error))
2076 {
2077 jvOutput[jss::status] = "error";
2078 if (jvOutput.isMember(jss::error_code))
2079 {
2080 nRet = std::stoi(jvOutput[jss::error_code].asString());
2081 }
2082 else if (jvOutput[jss::error].isMember(jss::error_code))
2083 {
2084 nRet = std::stoi(jvOutput[jss::error][jss::error_code].asString());
2085 }
2086 else
2087 {
2088 nRet = RpcBadSyntax;
2089 }
2090 }
2091
2092 // YYY We could have a command line flag for single line output for
2093 // scripts. YYY We would intercept output here and simplify it.
2094 }
2095 catch (RequestNotParsable const& e)
2096 {
2097 jvOutput = rpcError(RpcInvalidParams);
2098 jvOutput["error_what"] = e.what();
2099 nRet = RpcInvalidParams;
2100 }
2101 catch (std::exception& e)
2102 {
2103 jvOutput = rpcError(RpcInternal);
2104 jvOutput["error_what"] = e.what();
2105 nRet = RpcInternal;
2106 }
2107
2108 return {nRet, std::move(jvOutput)};
2109}
2110
2111//------------------------------------------------------------------------------
2112
2113namespace rpc_call {
2114
2115int
2116fromCommandLine(Config const& config, std::vector<std::string> const& vCmd, Logs& logs)
2117{
2118 auto const result = rpcClient(vCmd, config, logs, rpc::kApiCommandLineVersion);
2119
2120 std::cout << result.second.toStyledString();
2121
2122 return result.first;
2123}
2124
2125//------------------------------------------------------------------------------
2126
2127void
2129 boost::asio::io_context& ioContext,
2130 std::string const& strIp,
2131 std::uint16_t const iPort,
2132 std::string const& strUsername,
2133 std::string const& strPassword,
2134 std::string const& strPath,
2135 std::string const& strMethod,
2136 json::Value const& jvParams,
2137 bool const bSSL,
2138 bool const quiet,
2139 Logs& logs,
2140 std::function<void(json::Value const& jvInput)> callbackFuncP,
2142{
2143 auto j = logs.journal("HTTPClient");
2144
2145 // Connect to localhost
2146 if (!quiet)
2147 {
2148 JLOG(j.info()) << (bSSL ? "Securely connecting to " : "Connecting to ") << strIp << ":"
2149 << iPort << std::endl;
2150 }
2151
2152 // HTTP basic authentication
2153 headers["Authorization"] =
2154 std::string("Basic ") + base64Encode(strUsername + ":" + strPassword);
2155
2156 // Send request
2157
2158 // Number of bytes to try to receive if no
2159 // Content-Length header received
2160 constexpr auto kRpcReplyMaxBytes = megabytes(256);
2161
2162 using namespace std::chrono_literals;
2163 static constexpr auto kRpcWebhookTimeout = 30s;
2164
2166 bSSL,
2167 ioContext,
2168 strIp,
2169 iPort,
2170 [strMethod, jvParams, headers, strPath, j](
2171 boost::asio::streambuf& sb, std::string const& strHost) {
2172 RPCCallImp::onRequest(strMethod, jvParams, headers, strPath, sb, strHost, j);
2173 },
2174 kRpcReplyMaxBytes,
2175 kRpcWebhookTimeout,
2176 [callbackFuncP, j](
2177 boost::system::error_code const& ecResult, int iStatus, std::string const& strData) {
2178 return RPCCallImp::onResponse(callbackFuncP, ecResult, iStatus, strData, j);
2179 },
2180 j);
2181}
2182
2183} // namespace rpc_call
2184
2185} // namespace xrpl
T all_of(T... args)
T begin(T... args)
A generic endpoint for log messages.
Definition Journal.h:44
Stream debug() const
Definition Journal.h:344
Stream trace() const
Severity stream access functions.
Definition Journal.h:338
Stream warn() const
Definition Journal.h:356
Unserialize a JSON document into a Value.
Definition json_reader.h:20
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Represents a JSON value.
Definition json_value.h:117
const_iterator begin() const
bool isNull() const
isNull() tests to see if this field is null.
bool isObject() const
bool isArray() const
Value & append(Value const &value)
Append value to array at the end.
UInt size() const
Number of values in array or object.
const_iterator end() const
UInt asUInt() const
std::string asString() const
Returns the unquoted string value.
bool isObjectOrNull() const
bool isMember(char const *key) const
Return true if the object has a member named key.
Int asInt() const
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:525
std::optional< beast::ip::Endpoint > rpcIp
static void request(bool bSSL, boost::asio::io_context &ioContext, std::string strSite, unsigned short const port, std::function< void(boost::asio::streambuf &sb, std::string const &strHost)> build, std::size_t responseMax, std::chrono::seconds timeout, std::function< bool(boost::system::error_code const &ecResult, int iStatus, std::string const &strData)> complete, beast::Journal const &j)
Manages partitions for logging.
Definition Log.h:23
beast::Journal journal(std::string const &name)
Definition Log.cpp:137
json::Value parseManifest(json::Value const &jvParams)
Definition RPCCall.cpp:281
json::Value parseJson2(json::Value const &jvParams)
Definition RPCCall.cpp:667
json::Value parseLedgerId(json::Value const &jvParams)
Definition RPCCall.cpp:749
json::Value parseJson(json::Value const &jvParams)
Definition RPCCall.cpp:619
json::Value parseAccountTransactions(json::Value const &jvParams)
Definition RPCCall.cpp:317
json::Value parseSignFor(json::Value const &jvParams)
Definition RPCCall.cpp:591
RPCParser(unsigned apiVersion, beast::Journal j)
Definition RPCCall.cpp:1742
json::Value parseLedgerEntry(json::Value const &jvParams)
Definition RPCCall.cpp:770
json::Value parseAccountItems(json::Value const &jvParams)
Definition RPCCall.cpp:809
json::Value parseEvented(json::Value const &jvParams)
Definition RPCCall.cpp:535
static bool validPublicKey(std::string const &strPk, TokenType type=TokenType::AccountPublic)
Definition RPCCall.cpp:232
json::Value parseChannelAuthorize(json::Value const &jvParams)
Definition RPCCall.cpp:837
json::Value parseFeature(json::Value const &jvParams)
Definition RPCCall.cpp:543
json::Value parseChannelVerify(json::Value const &jvParams)
Definition RPCCall.cpp:881
json::Value parseInternal(json::Value const &jvParams)
Definition RPCCall.cpp:264
json::Value parseAccountRaw1(json::Value const &jvParams)
Definition RPCCall.cpp:952
json::Value parseTxHistory(json::Value const &jvParams)
Definition RPCCall.cpp:1203
json::Value parseRipplePathFind(json::Value const &jvParams)
Definition RPCCall.cpp:1015
json::Value parseValidationCreate(json::Value const &jvParams)
Definition RPCCall.cpp:1220
json::Value parseServerDefinitions(json::Value const &jvParams)
Definition RPCCall.cpp:1294
json::Value parseServerInfo(json::Value const &jvParams)
Definition RPCCall.cpp:1309
json::Value parseCommand(std::string_view strMethod, json::Value const &jvParams, bool allowAnyCommand)
Definition RPCCall.cpp:1751
json::Value parseSubmitMultiSigned(json::Value const &jvParams)
Definition RPCCall.cpp:1124
json::Value parsePeerReservationsDel(json::Value const &jvParams)
Definition RPCCall.cpp:1006
json::Value parseGetCounts(json::Value const &jvParams)
Definition RPCCall.cpp:577
json::Value parseFetchInfo(json::Value const &jvParams)
Definition RPCCall.cpp:302
static std::span< std::string_view const > methodNames()
Names of every method the command line accepts.
Definition RPCCall.cpp:1706
json::Value parseLogLevel(json::Value const &jvParams)
Definition RPCCall.cpp:788
static json::Value jvParseCurrencyIssuer(std::string const &strCurrencyIssuer)
Definition RPCCall.cpp:199
json::Value parseWalletPropose(json::Value const &jvParams)
Definition RPCCall.cpp:1235
static constexpr auto kSortedCommands
Definition RPCCall.cpp:1682
json::Value parseAccountCurrencies(json::Value const &jvParams)
Definition RPCCall.cpp:815
static constexpr bool commandsValid()
Whether the command table is well formed.
Definition RPCCall.cpp:1727
static constexpr auto kCommandArray
Definition RPCCall.cpp:1322
json::Value parseVault(json::Value const &jvParams)
Definition RPCCall.cpp:973
json::Value parseGatewayBalances(json::Value const &jvParams)
Definition RPCCall.cpp:1251
json::Value parseTx(json::Value const &jvParams)
Definition RPCCall.cpp:1170
static bool jvParseLedger(json::Value &jvRequest, std::string const &strLedger)
Definition RPCCall.cpp:178
json::Value parseSimulate(json::Value const &jvParams)
Definition RPCCall.cpp:1042
json::Value parseConnect(json::Value const &jvParams)
Definition RPCCall.cpp:483
json::Value parseSignSubmit(json::Value const &jvParams)
Definition RPCCall.cpp:1074
json::Value parseBookOffers(json::Value const &jvParams)
Definition RPCCall.cpp:393
json::Value parseAccountLines(json::Value const &jvParams)
Definition RPCCall.cpp:822
json::Value parseAccountChannels(json::Value const &jvParams)
Definition RPCCall.cpp:829
json::Value parseTransactionEntry(json::Value const &jvParams)
Definition RPCCall.cpp:1144
unsigned const apiVersion_
Definition RPCCall.cpp:172
json::Value parseAsIs(json::Value const &jvParams)
Definition RPCCall.cpp:252
bool isValidJson2(json::Value const &jv)
Definition RPCCall.cpp:641
beast::Journal const j_
Definition RPCCall.cpp:173
json::Value parseCanDelete(json::Value const &jvParams)
Definition RPCCall.cpp:460
json::Value parseDepositAuthorized(json::Value const &jvParams)
Definition RPCCall.cpp:512
json::Value(RPCParser::*)(json::Value const &jvParams) ParseFuncPtr
Definition RPCCall.cpp:248
json::Value parsePeerReservationsAdd(json::Value const &jvParams)
Definition RPCCall.cpp:992
json::Value parseLedger(json::Value const &jvParams)
Definition RPCCall.cpp:719
json::Value parseAccountRaw2(json::Value const &jvParams, char const *const acc2Field)
Definition RPCCall.cpp:910
static constexpr auto kCommandNames
Definition RPCCall.cpp:1695
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_last_of(T... args)
T for_each(T... args)
T is_sorted(T... args)
T lower_bound(T... args)
T max(T... args)
constexpr Out lexicalCast(In in, Out defaultValue=Out())
Convert from one type to another.
BasicLogstream< char > LogStream
Definition Journal.h:474
constexpr Zero kZero
Definition Zero.h:30
unsigned int UInt
@ Array
array value (ordered list)
Definition json_value.h:28
@ Object
object value (collection of name/value pairs).
Definition json_value.h:29
constexpr std::string_view kInternal
Definition MethodNames.h:43
constexpr std::string_view kAccountNfts
Definition MethodNames.h:23
constexpr std::string_view kPing
Definition MethodNames.h:67
constexpr std::string_view kAccountLines
Definition MethodNames.h:22
constexpr std::string_view kBookOffers
Definition MethodNames.h:30
constexpr std::string_view kAccountOffers
Definition MethodNames.h:25
constexpr std::string_view kConnect
Definition MethodNames.h:34
constexpr std::string_view kRipplePathFind
Definition MethodNames.h:70
constexpr std::string_view kAccountCurrencies
Definition MethodNames.h:20
constexpr std::string_view kLedgerCurrent
Definition MethodNames.h:50
constexpr std::string_view kPeerReservationsAdd
Definition MethodNames.h:63
constexpr std::string_view kChannelAuthorize
Definition MethodNames.h:32
constexpr std::string_view kAccountChannels
Names of the RPC methods the server accepts.
Definition MethodNames.h:19
constexpr std::string_view kPeerReservationsDel
Definition MethodNames.h:64
constexpr std::string_view kLogLevel
Definition MethodNames.h:55
constexpr std::string_view kSubmitMultisigned
Definition MethodNames.h:79
constexpr std::string_view kWalletPropose
Definition MethodNames.h:93
constexpr std::string_view kLedgerAccept
Definition MethodNames.h:47
constexpr std::string_view kLedger
Definition MethodNames.h:46
constexpr std::string_view kAccountTx
Definition MethodNames.h:26
constexpr std::string_view kBookChanges
Definition MethodNames.h:29
constexpr std::string_view kValidationCreate
Definition MethodNames.h:87
constexpr std::string_view kConsensusInfo
Definition MethodNames.h:35
constexpr std::string_view kJson2
Definition MethodNames.h:45
constexpr std::string_view kOwnerInfo
Definition MethodNames.h:61
constexpr std::string_view kDepositAuthorized
Definition MethodNames.h:36
constexpr std::string_view kServerDefinitions
Definition MethodNames.h:71
constexpr std::string_view kAmmInfo
Definition MethodNames.h:27
constexpr std::string_view kCanDelete
Definition MethodNames.h:31
constexpr std::string_view kLogrotate
Definition MethodNames.h:56
constexpr std::string_view kLedgerEntry
Definition MethodNames.h:52
constexpr std::string_view kChannelVerify
Definition MethodNames.h:33
constexpr std::string_view kPeers
Definition MethodNames.h:66
constexpr std::string_view kSign
Definition MethodNames.h:74
constexpr std::string_view kGetCounts
Definition MethodNames.h:42
constexpr std::string_view kVersion
Definition MethodNames.h:92
constexpr std::string_view kPathFind
Definition MethodNames.h:62
constexpr std::string_view kServerInfo
Definition MethodNames.h:72
constexpr std::string_view kAccountObjects
Definition MethodNames.h:24
constexpr std::string_view kManifest
Definition MethodNames.h:57
constexpr std::string_view kLedgerHeader
Definition MethodNames.h:53
constexpr std::string_view kSubmit
Definition MethodNames.h:78
constexpr std::string_view kStop
Definition MethodNames.h:77
constexpr std::string_view kLedgerClosed
Definition MethodNames.h:49
constexpr std::string_view kFetchInfo
Definition MethodNames.h:39
constexpr std::string_view kTxHistory
Definition MethodNames.h:83
constexpr std::string_view kSubscribe
Definition MethodNames.h:80
constexpr std::string_view kValidatorInfo
Definition MethodNames.h:88
constexpr std::string_view kTx
Definition MethodNames.h:82
constexpr std::string_view kPrint
Definition MethodNames.h:68
constexpr std::string_view kTransactionEntry
Definition MethodNames.h:81
constexpr std::string_view kVaultInfo
Definition MethodNames.h:91
constexpr std::string_view kSimulate
Definition MethodNames.h:76
constexpr std::string_view kSignFor
Definition MethodNames.h:75
constexpr std::string_view kPeerReservationsList
Definition MethodNames.h:65
constexpr std::string_view kFeature
Definition MethodNames.h:37
constexpr std::string_view kLedgerRequest
Definition MethodNames.h:54
constexpr std::string_view kUnlList
Definition MethodNames.h:85
constexpr std::string_view kJson
Definition MethodNames.h:44
constexpr std::string_view kRandom
Definition MethodNames.h:69
constexpr std::string_view kServerState
Definition MethodNames.h:73
constexpr std::string_view kAccountInfo
Definition MethodNames.h:21
constexpr std::string_view kUnsubscribe
Definition MethodNames.h:86
constexpr std::string_view kGatewayBalances
Definition MethodNames.h:40
Processes XRPL RPC calls.
Definition RPCCall.cpp:2113
void fromNetwork(boost::asio::io_context &ioContext, std::string const &strIp, std::uint16_t const iPort, std::string const &strUsername, std::string const &strPassword, std::string const &strPath, std::string const &strMethod, json::Value const &jvParams, bool const bSSL, bool const quiet, Logs &logs, std::function< void(json::Value const &jvInput)> callbackFuncP, std::unordered_map< std::string, std::string > headers)
Definition RPCCall.cpp:2128
int fromCommandLine(Config const &config, std::vector< std::string > const &vCmd, Logs &logs)
Definition RPCCall.cpp:2116
json::Value makeParamError(std::string const &message)
Returns a new json object that indicates invalid parameters.
Definition ErrorCodes.h:231
json::Value invalidFieldError(std::string const &name)
Definition ErrorCodes.h:285
static constexpr auto kApiCommandLineVersion
Definition ApiVersion.h:45
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
@ RpcChannelAmtMalformed
Definition ErrorCodes.h:84
@ RpcInternal
Definition ErrorCodes.h:113
@ RpcBadKeyType
Definition ErrorCodes.h:116
@ RpcSuccess
Definition ErrorCodes.h:27
@ RpcActMalformed
Definition ErrorCodes.h:73
@ RpcNotSynced
Definition ErrorCodes.h:50
@ RpcLgrIdxsInvalid
Definition ErrorCodes.h:95
@ RpcPublicMalformed
Definition ErrorCodes.h:100
@ RpcJsonRpc
Definition ErrorCodes.h:30
@ RpcNoEvents
Definition ErrorCodes.h:37
@ RpcInvalidParams
Definition ErrorCodes.h:67
@ RpcBadSyntax
Definition ErrorCodes.h:29
@ RpcChannelMalformed
Definition ErrorCodes.h:83
@ RpcLgrIdxMalformed
Definition ErrorCodes.h:96
@ RpcUnknownCommand
Definition ErrorCodes.h:68
ServerHandler::Setup setupServerHandler(Config const &config, std::ostream &log)
std::optional< KeyType > keyTypeFromString(std::string const &s)
Definition KeyType.h:14
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:95
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:657
std::string jsonrpcRequest(std::string const &strMethod, json::Value const &params, json::Value const &id)
Definition RPCCall.cpp:1813
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Slice makeSlice(std::array< T, N > const &a)
Definition Slice.h:228
json::Value rpcError(ErrorCodeI iError)
Definition RPCErr.cpp:13
BaseUInt< 256 > UInt256
Definition base_uint.h:580
json::Value rpcCmdToJson(std::vector< std::string > const &args, json::Value &retParams, unsigned int apiVersion, beast::Journal j)
Definition RPCCall.cpp:1916
constexpr auto megabytes(T value) noexcept
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
std::span< std::string_view const > commandLineMethodNames()
Return the names of all methods accepted on the command line.
Definition RPCCall.cpp:1909
static std::string const & systemName()
std::string base64Encode(std::uint8_t const *data, std::size_t len)
std::optional< std::uint64_t > toUInt64(std::string const &s)
TokenType
Definition tokens.h:19
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:1961
bool isRpcError(json::Value jvResult)
Definition RPCErr.cpp:22
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:142
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:52
T parse(T... args)
T size(T... args)
T sort(T... args)
T starts_with(T... args)
T stoi(T... args)
T str(T... args)
static bool onResponse(std::function< void(json::Value const &jvInput)> callbackFuncP, boost::system::error_code const &ecResult, int iStatus, std::string const &strData, beast::Journal j)
Definition RPCCall.cpp:1843
RPCCallImp()=default
static void callRPCHandler(json::Value *jvOutput, json::Value const &jvInput)
Definition RPCCall.cpp:1837
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:1889
T transform(T... args)