20 #include <ripple/app/main/Application.h>
21 #include <ripple/basics/StringUtilities.h>
22 #include <ripple/basics/ByteUtilities.h>
23 #include <ripple/net/RPCCall.h>
24 #include <ripple/net/RPCErr.h>
25 #include <ripple/basics/base64.h>
26 #include <ripple/basics/contract.h>
27 #include <ripple/basics/Log.h>
28 #include <ripple/core/Config.h>
29 #include <ripple/json/json_reader.h>
30 #include <ripple/json/to_string.h>
31 #include <ripple/json/Object.h>
32 #include <ripple/net/HTTPClient.h>
33 #include <ripple/protocol/ErrorCodes.h>
34 #include <ripple/protocol/Feature.h>
35 #include <ripple/protocol/jss.h>
36 #include <ripple/protocol/SystemParameters.h>
37 #include <ripple/protocol/UintTypes.h>
38 #include <ripple/rpc/ServerHandler.h>
39 #include <ripple/rpc/impl/RPCHelpers.h>
40 #include <ripple/beast/core/LexicalCast.h>
42 #include <boost/algorithm/string/predicate.hpp>
43 #include <boost/beast/core/string.hpp>
44 #include <boost/asio/streambuf.hpp>
45 #include <boost/optional.hpp>
46 #include <boost/regex.hpp>
77 << (strPath.
empty () ?
"/" : strPath)
79 <<
"User-Agent: " <<
systemName () <<
"-json-rpc/v1\r\n"
80 <<
"Host: " << strHost <<
"\r\n"
81 <<
"Content-Type: application/json\r\n"
82 <<
"Content-Length: " << strMsg.
size () <<
"\r\n"
83 <<
"Accept: application/json\r\n";
85 for (
auto const& [k,v] : mapRequestHeaders)
86 s << k <<
": " << v <<
"\r\n";
88 s <<
"\r\n" << strMsg;
101 if (strLedger ==
"current" || strLedger ==
"closed" || strLedger ==
"validated")
103 jvRequest[jss::ledger_index] = strLedger;
105 else if (strLedger.
length () == 64)
108 jvRequest[jss::ledger_hash] = strLedger;
112 jvRequest[jss::ledger_index] = beast::lexicalCast <std::uint32_t> (strLedger);
121 static boost::regex reCurIss (
"\\`([[:alpha:]]{3})(?:/(.+))?\\'");
123 boost::smatch smMatch;
125 if (boost::regex_match (strCurrencyIssuer, smMatch, reCurIss))
131 jvResult[jss::currency] = strCurrency;
136 jvResult[jss::issuer] = strIssuer;
144 strCurrencyIssuer +
"'");
171 v[jss::params] = jvParams;
179 unsigned int sz {jvParams.
size()};
185 if (boost::iequals(jvParams[0u].asString(),
"novalidate"))
187 else if (!boost::iequals(jvParams[--sz].asString(),
"novalidate"))
193 for (; i < sz; i += 2)
196 shard[jss::index] = jvParams[i].
asUInt();
197 shard[jss::url] = jvParams[i + 1].
asString();
198 shards.
append(std::move(shard));
200 jvResult[jss::shards] = std::move(shards);
208 v[jss::internal_command] = jvParams[0u];
212 for (
unsigned i = 1; i < jvParams.
size (); ++i)
213 params.
append (jvParams[i]);
215 v[jss::params] = params;
222 if (jvParams.
size () == 1)
230 jvRequest[jss::public_key] = strPk;
242 unsigned int iParams = jvParams.
size ();
245 jvRequest[jvParams[0u].
asString()] =
true;
255 unsigned int iParams = jvParams.
size ();
258 parseBase58<AccountID>(jvParams[0u].asString());
262 jvRequest[jss::account]=
toBase58(*account);
266 while (!bDone && iParams >= 2)
269 if (jvParams[iParams - 1].asString () == jss::binary)
271 jvRequest[jss::binary] =
true;
274 else if (jvParams[iParams - 1].asString () == jss::count)
276 jvRequest[jss::count] =
true;
279 else if (jvParams[iParams - 1].asString () == jss::descending)
281 jvRequest[jss::descending] =
true;
293 else if (2 == iParams)
303 if (uLedgerMax != -1 && uLedgerMax < uLedgerMin)
308 jvRequest[jss::ledger_index_min] = jvParams[1u].
asInt ();
309 jvRequest[jss::ledger_index_max] = jvParams[2u].
asInt ();
312 jvRequest[jss::limit] = jvParams[3u].
asInt ();
315 jvRequest[jss::offset] = jvParams[4u].
asInt ();
325 unsigned int iParams = jvParams.
size ();
328 parseBase58<AccountID>(jvParams[0u].asString());
332 jvRequest[jss::account] =
toBase58(*account);
336 while (!bDone && iParams >= 2)
338 if (jvParams[iParams - 1].asString () == jss::binary)
340 jvRequest[jss::binary] =
true;
343 else if (jvParams[iParams - 1].asString () == jss::count)
345 jvRequest[jss::count] =
true;
348 else if (jvParams[iParams - 1].asString () == jss::forward)
350 jvRequest[jss::forward] =
true;
362 else if (2 == iParams)
372 if (uLedgerMax != -1 && uLedgerMax < uLedgerMin)
377 jvRequest[jss::ledger_index_min] = jvParams[1u].
asInt ();
378 jvRequest[jss::ledger_index_max] = jvParams[2u].
asInt ();
381 jvRequest[jss::limit] = jvParams[3u].
asInt ();
405 jvRequest[jss::taker_pays] = jvTakerPays;
414 jvRequest[jss::taker_gets] = jvTakerGets;
417 if (jvParams.
size () >= 3)
419 jvRequest[jss::issuer] = jvParams[2u].
asString ();
422 if (jvParams.
size () >= 4 && !
jvParseLedger (jvRequest, jvParams[3u].asString ()))
425 if (jvParams.
size () >= 5)
427 int iLimit = jvParams[5u].
asInt ();
430 jvRequest[jss::limit] = iLimit;
433 if (jvParams.
size () >= 6 && jvParams[5u].
asInt ())
435 jvRequest[jss::proof] =
true;
438 if (jvParams.
size () == 7)
439 jvRequest[jss::marker] = jvParams[6u];
449 if (!jvParams.
size ())
455 jvRequest[
"can_delete"] = jvParams[0u].
asUInt();
457 jvRequest[
"can_delete"] = input;
467 jvRequest[jss::ip] = jvParams[0u].
asString ();
469 if (jvParams.
size () == 2)
470 jvRequest[jss::port] = jvParams[1u].
asUInt ();
479 jvRequest[jss::source_account] = jvParams[0u].
asString ();
480 jvRequest[jss::destination_account] = jvParams[1u].
asString ();
482 if (jvParams.
size () == 3)
499 if (jvParams.
size () > 0)
500 jvRequest[jss::feature] = jvParams[0u].
asString ();
502 if (jvParams.
size () > 1)
504 auto const action = jvParams[1u].
asString ();
509 if (boost::iequals(action,
"reject"))
511 else if (boost::iequals(action,
"accept"))
525 if (jvParams.
size ())
526 jvRequest[jss::min_count] = jvParams[0u].
asUInt ();
535 bool const bOffline = 4 == jvParams.
size () && jvParams[3u].
asString () ==
"offline";
537 if (3 == jvParams.
size () || bOffline)
546 jvRequest[jss::account] = jvParams[0u].
asString ();
547 jvRequest[jss::secret] = jvParams[1u].
asString ();
548 jvRequest[jss::tx_json] = txJSON;
551 jvRequest[jss::offline] =
true;
565 JLOG (
j_.
trace()) <<
"RPC method: " << jvParams[0u];
566 JLOG (
j_.
trace()) <<
"RPC json: " << jvParams[1u];
573 jvRequest[jss::method] = jvParams[0u];
587 for (
auto const& j : jv)
596 if (jv.
isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0" &&
597 jv.
isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0" &&
614 bool valid_parse = reader.
parse(jvParams[0u].asString(), jv);
622 auto const& params = jv[jss::params];
623 for (
auto i = params.begin(); i != params.end(); ++i)
624 jv1[i.key().asString()] = *i;
626 jv1[jss::jsonrpc] = jv[jss::jsonrpc];
627 jv1[jss::ripplerpc] = jv[jss::ripplerpc];
628 jv1[jss::id] = jv[jss::id];
629 jv1[jss::method] = jv[jss::method];
636 if (jv[j].isMember(jss::params))
638 auto const& params = jv[j][jss::params];
639 for (
auto i = params.begin(); i != params.end(); ++i)
640 jv1[j][i.key().asString()] = *i;
642 jv1[j][jss::jsonrpc] = jv[j][jss::jsonrpc];
643 jv1[j][jss::ripplerpc] = jv[j][jss::ripplerpc];
644 jv1[j][jss::id] = jv[j][jss::id];
645 jv1[j][jss::method] = jv[j][jss::method];
651 jv_error[jss::jsonrpc] = jv[jss::jsonrpc];
653 jv_error[jss::ripplerpc] = jv[jss::ripplerpc];
655 jv_error[jss::id] = jv[jss::id];
664 if (!jvParams.
size ())
671 if (2 == jvParams.
size ())
673 if (jvParams[1u].asString () ==
"full")
675 jvRequest[jss::full] =
true;
677 else if (jvParams[1u].asString () ==
"tx")
679 jvRequest[jss::transactions] =
true;
680 jvRequest[jss::expand] =
true;
694 if (strLedger.
length () == 64)
696 jvRequest[jss::ledger_hash] = strLedger;
700 jvRequest[jss::ledger_index] = beast::lexicalCast <std::uint32_t> (strLedger);
713 if (jvParams.
size () == 1)
715 jvRequest[jss::severity] = jvParams[0u].
asString ();
717 else if (jvParams.
size () == 2)
719 jvRequest[jss::partition] = jvParams[0u].
asString ();
720 jvRequest[jss::severity] = jvParams[1u].
asString ();
758 unsigned int index = 0;
760 if (jvParams.
size() == 4)
762 jvRequest[jss::passphrase] = jvParams[index];
767 jvRequest[jss::key_type] = jvParams[index];
772 jvRequest[jss::secret] = jvParams[index];
781 jvRequest[jss::channel_id] =
to_string(channelId);
785 if (!jvParams[index].isString() || !
to_uint64(jvParams[index].asString()))
787 jvRequest[jss::amount] = jvParams[index];
804 jvRequest[jss::public_key] = strPk;
811 jvRequest[jss::channel_id] = jvParams[1u].
asString ();
813 if (!jvParams[2u].isString() || !
to_uint64(jvParams[2u].asString()))
815 jvRequest[jss::amount] = jvParams[2u];
817 jvRequest[jss::signature] = jvParams[3u].
asString ();
823 char const *
const acc2Field)
826 auto const nParams = jvParams.
size ();
828 for (
auto i = 0; i < nParams; ++i)
832 if (i==1 && strParam.
empty())
838 if (parseBase58<PublicKey> (
840 parseBase58<AccountID> (strParam) ||
843 jvRequest[accFields[i]] = std::move (strParam);
865 unsigned int iCursor = jvParams.
size ();
866 bool bStrict =
false;
868 if (iCursor >= 2 && jvParams[iCursor - 1] == jss::strict)
875 ! parseBase58<AccountID>(strIdent) &&
882 jvRequest[jss::account] = strIdent;
885 jvRequest[jss::strict] = 1;
887 if (iCursor == 2 && !
jvParseLedger (jvRequest, jvParams[1u].asString ()))
897 jvRequest[jss::public_key] = jvParams[0u].
asString();
898 if (jvParams.
size() > 1)
900 jvRequest[jss::description] = jvParams[1u].
asString();
909 jvRequest[jss::public_key] = jvParams[0u].
asString();
918 bool bLedger = 2 == jvParams.
size ();
920 JLOG (
j_.
trace()) <<
"RPC json: " << jvParams[0u];
944 bool const bOffline = 3 == jvParams.
size () && jvParams[2u].
asString () ==
"offline";
946 if (1 == jvParams.
size ())
952 jvRequest[jss::tx_blob] = jvParams[0u].
asString ();
956 else if ((2 == jvParams.
size () || bOffline)
962 jvRequest[jss::secret] = jvParams[0u].
asString ();
963 jvRequest[jss::tx_json] = txJSON;
966 jvRequest[jss::offline] =
true;
979 if (1 == jvParams.
size ())
986 jvRequest[jss::tx_json] = txJSON;
998 assert (jvParams.
size() == 2);
1001 if (txHash.
length() != 64)
1005 jvRequest[jss::tx_hash] = txHash;
1011 if (jvRequest.isMember(jss::ledger_index) &&
1012 jvRequest[jss::ledger_index] == 0)
1023 if (jvParams.
size () == 2 || jvParams.
size () == 4)
1025 if (jvParams[1u].asString () == jss::binary)
1026 jvRequest[jss::binary] =
true;
1029 if (jvParams.
size () >= 3)
1031 const auto offset = jvParams.
size () == 3 ? 0 : 1;
1033 jvRequest[jss::min_ledger] = jvParams[1u + offset].
asString ();
1034 jvRequest[jss::max_ledger] = jvParams[2u + offset].
asString ();
1037 jvRequest[jss::transaction] = jvParams[0u].
asString ();
1046 jvRequest[jss::start] = jvParams[0u].
asUInt ();
1059 if (jvParams.
size ())
1060 jvRequest[jss::secret] = jvParams[0u].
asString ();
1071 if (jvParams.
size ())
1072 jvRequest[jss::passphrase] = jvParams[0u].
asString ();
1082 unsigned int index = 0;
1083 const unsigned int size = jvParams.
size ();
1091 if (param[0] !=
'r')
1093 if (param.
size() == 64)
1094 jvRequest[jss::ledger_hash] = param;
1096 jvRequest[jss::ledger_index] = param;
1101 param = jvParams[index++].
asString ();
1104 jvRequest[jss::account] = param;
1110 while (index < size)
1111 hotWallets.
append (jvParams[index++].asString ());
1121 if (jvParams.
size() == 1 && jvParams[0u].
asString() ==
"counters")
1122 jvRequest[jss::counters] =
true;
1141 stream <<
"Method: '" << strMethod <<
"'";
1142 stream <<
"Params: " << jvParams;
1157 Command
const commands[] =
1228 auto const count = jvParams.
size ();
1230 for (
auto const& command : commands)
1232 if (strMethod == command.name)
1234 if ((command.minParams >= 0 && count < command.minParams) ||
1235 (command.maxParams >= 0 && count > command.maxParams))
1238 "Wrong number of parameters for " << command.name <<
1239 " minimum=" << command.minParams <<
1240 " maximum=" << command.maxParams <<
1241 " actual=" << count;
1246 return (this->* (command.parse)) (jvParams);
1251 if (!allowAnyCommand)
1272 request[jss::method] = strMethod;
1273 request[jss::params] = params;
1274 request[jss::id] = id;
1295 (*jvOutput) = jvInput;
1300 const boost::system::error_code& ecResult,
int iStatus,
1309 Throw<std::runtime_error> (
1310 "incorrect rpcuser or rpcpassword (authorization failed)");
1311 else if ((iStatus >= 400) && (iStatus != 400) && (iStatus != 404) && (iStatus != 500))
1312 Throw<std::runtime_error> (
1315 else if (strData.
empty ())
1316 Throw<std::runtime_error> (
"no response from server");
1320 if (strData.
find(
"Unable to parse request") == 0)
1321 Throw<RequestNotParseable> (strData);
1324 if (!reader.
parse (strData, jvReply))
1325 Throw<std::runtime_error> (
"couldn't parse reply from server");
1328 Throw<std::runtime_error> (
"expected reply to have result, error and id properties");
1332 jvResult[
"result"] = jvReply;
1334 (callbackFuncP) (jvResult);
1346 boost::asio::streambuf& sb,
1350 JLOG (j.
debug()) <<
"requestRPC: strPath='" << strPath <<
"'";
1374 for (
int i = 1; i != args.
size (); i++)
1375 jvRpcParams.
append (args[i]);
1379 retParams[jss::method] = args[0];
1380 retParams[jss::params] = jvRpcParams;
1382 jvRequest = rpParser.
parseCommand (args[0], jvRpcParams,
true);
1385 if( jr.isObject() &&
1386 !jr.isMember(jss::error) &&
1387 !jr.isMember(jss::api_version))
1394 insert_api_version(jvRequest);
1412 jv[jss::method] = paramsObj.
isMember (jss::method) ?
1413 paramsObj[jss::method].asString() : args[0];
1416 if (paramsObj.begin() != paramsObj.end())
1419 paramsArray.append (paramsObj);
1421 if (paramsObj.isMember(jss::jsonrpc))
1422 jv[jss::jsonrpc] = paramsObj[jss::jsonrpc];
1423 if (paramsObj.isMember(jss::ripplerpc))
1424 jv[jss::ripplerpc] = paramsObj[jss::ripplerpc];
1425 if (paramsObj.isMember(jss::id))
1426 jv[jss::id] = paramsObj[jss::id];
1438 "Expect specific rpc enum values.");
1451 if (jvRequest.
isMember (jss::error))
1453 jvOutput = jvRequest;
1454 jvOutput[
"rpc"] = jvRpc;
1486 jvParams.
append (jvRequest);
1490 jvParams.
append(jvRequest[i]);
1494 boost::asio::io_service isService;
1503 ? jvRequest[jss::method].
asString ()
1512 std::placeholders::_1),
1519 jvOutput = jvOutput[
"result"];
1530 jvOutput[
"result"] = jvRpcError;
1534 if (jvOutput.
isMember (jss::error))
1536 jvOutput[
"rpc"] = jvRpc;
1537 jvOutput[
"request_sent"] = jvRequest;
1541 if (jvOutput.
isMember (jss::error))
1543 jvOutput[jss::status] =
"error";
1544 if (jvOutput.
isMember(jss::error_code))
1545 nRet =
std::stoi(jvOutput[jss::error_code].asString());
1546 else if (jvOutput[jss::error].isMember(jss::error_code))
1547 nRet =
std::stoi(jvOutput[jss::error][jss::error_code].asString());
1555 catch (RequestNotParseable& e)
1558 jvOutput[
"error_what"] = e.what();
1564 jvOutput[
"error_what"] = e.
what ();
1568 return { nRet, std::move(jvOutput) };
1580 auto const result =
rpcClient(vCmd, config, logs);
1582 std::cout << result.second.toStyledString ();
1584 return result.first;
1590 boost::asio::io_service& io_service,
1594 Json::Value const& jvParams,
const bool bSSL,
const bool quiet,
1599 auto j = logs.
journal (
"HTTPClient");
1604 JLOG(j.info()) << (bSSL ?
"Securely connecting to " :
"Connecting to ") <<
1610 strUsername +
":" + strPassword);
1616 constexpr
auto RPC_REPLY_MAX_BYTES =
megabytes(256);
1618 using namespace std::chrono_literals;
1619 auto constexpr RPC_NOTIFY = 10min;
1631 strPath, std::placeholders::_1, std::placeholders::_2, j),
1632 RPC_REPLY_MAX_BYTES,
1635 std::placeholders::_1, std::placeholders::_2,
1636 std::placeholders::_3, j),