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