20 #include <ripple/app/main/Application.h>
21 #include <ripple/basics/ByteUtilities.h>
22 #include <ripple/basics/Log.h>
23 #include <ripple/basics/StringUtilities.h>
24 #include <ripple/basics/base64.h>
25 #include <ripple/basics/contract.h>
26 #include <ripple/beast/core/LexicalCast.h>
27 #include <ripple/core/Config.h>
28 #include <ripple/json/Object.h>
29 #include <ripple/json/json_reader.h>
30 #include <ripple/json/to_string.h>
31 #include <ripple/net/HTTPClient.h>
32 #include <ripple/net/RPCCall.h>
33 #include <ripple/net/RPCErr.h>
34 #include <ripple/protocol/ErrorCodes.h>
35 #include <ripple/protocol/Feature.h>
36 #include <ripple/protocol/SystemParameters.h>
37 #include <ripple/protocol/UintTypes.h>
38 #include <ripple/protocol/jss.h>
39 #include <ripple/rpc/ServerHandler.h>
40 #include <ripple/rpc/impl/RPCHelpers.h>
42 #include <boost/algorithm/string/predicate.hpp>
43 #include <boost/asio/streambuf.hpp>
44 #include <boost/beast/core/string.hpp>
45 #include <boost/regex.hpp>
76 s <<
"POST " << (strPath.
empty() ?
"/" : strPath) <<
" HTTP/1.0\r\n"
77 <<
"User-Agent: " <<
systemName() <<
"-json-rpc/v1\r\n"
78 <<
"Host: " << strHost <<
"\r\n"
79 <<
"Content-Type: application/json\r\n"
80 <<
"Content-Length: " << strMsg.
size() <<
"\r\n"
81 <<
"Accept: application/json\r\n";
83 for (
auto const& [k, v] : mapRequestHeaders)
84 s << k <<
": " << v <<
"\r\n";
86 s <<
"\r\n" << strMsg;
101 if (strLedger ==
"current" || strLedger ==
"closed" ||
102 strLedger ==
"validated")
104 jvRequest[jss::ledger_index] = strLedger;
106 else if (strLedger.
length() == 64)
109 jvRequest[jss::ledger_hash] = strLedger;
113 jvRequest[jss::ledger_index] =
114 beast::lexicalCast<std::uint32_t>(strLedger);
129 static boost::regex reCurIss(
130 "\\`([][:alnum:]<>(){}[|?!@#$%^&*]{3})(?:/(.+))?\\'");
132 boost::smatch smMatch;
134 if (boost::regex_match(strCurrencyIssuer, smMatch, reCurIss))
140 jvResult[jss::currency] = strCurrency;
145 jvResult[jss::issuer] = strIssuer;
153 std::string(
"Invalid currency/issuer '") + strCurrencyIssuer +
163 if (parseBase58<PublicKey>(type, strPk))
186 v[jss::params] = jvParams;
195 unsigned int sz{jvParams.
size()};
201 if (boost::iequals(jvParams[0u].asString(),
"novalidate"))
203 else if (!boost::iequals(jvParams[--sz].asString(),
"novalidate"))
209 for (; i < sz; i += 2)
212 shard[jss::index] = jvParams[i].
asUInt();
213 shard[jss::url] = jvParams[i + 1].
asString();
214 shards.
append(std::move(shard));
216 jvResult[jss::shards] = std::move(shards);
225 v[jss::internal_command] = jvParams[0u];
229 for (
unsigned i = 1; i < jvParams.
size(); ++i)
230 params.
append(jvParams[i]);
232 v[jss::params] = params;
240 if (jvParams.
size() == 1)
248 jvRequest[jss::public_key] = strPk;
261 unsigned int iParams = jvParams.
size();
264 jvRequest[jvParams[0u].
asString()] =
true;
275 unsigned int iParams = jvParams.
size();
277 auto const account = parseBase58<AccountID>(jvParams[0u].asString());
281 jvRequest[jss::account] =
toBase58(*account);
285 while (!bDone && iParams >= 2)
288 if (jvParams[iParams - 1].asString() == jss::binary)
290 jvRequest[jss::binary] =
true;
293 else if (jvParams[iParams - 1].asString() == jss::count)
295 jvRequest[jss::count] =
true;
298 else if (jvParams[iParams - 1].asString() == jss::descending)
300 jvRequest[jss::descending] =
true;
312 else if (2 == iParams)
322 if (uLedgerMax != -1 && uLedgerMax < uLedgerMin)
330 jvRequest[jss::ledger_index_min] = jvParams[1u].
asInt();
331 jvRequest[jss::ledger_index_max] = jvParams[2u].
asInt();
334 jvRequest[jss::limit] = jvParams[3u].
asInt();
337 jvRequest[jss::offset] = jvParams[4u].
asInt();
349 unsigned int iParams = jvParams.
size();
351 auto const account = parseBase58<AccountID>(jvParams[0u].asString());
355 jvRequest[jss::account] =
toBase58(*account);
359 while (!bDone && iParams >= 2)
361 if (jvParams[iParams - 1].asString() == jss::binary)
363 jvRequest[jss::binary] =
true;
366 else if (jvParams[iParams - 1].asString() == jss::count)
368 jvRequest[jss::count] =
true;
371 else if (jvParams[iParams - 1].asString() == jss::forward)
373 jvRequest[jss::forward] =
true;
385 else if (2 == iParams)
395 if (uLedgerMax != -1 && uLedgerMax < uLedgerMin)
403 jvRequest[jss::ledger_index_min] = jvParams[1u].
asInt();
404 jvRequest[jss::ledger_index_max] = jvParams[2u].
asInt();
407 jvRequest[jss::limit] = jvParams[3u].
asInt();
433 jvRequest[jss::taker_pays] = jvTakerPays;
442 jvRequest[jss::taker_gets] = jvTakerGets;
445 if (jvParams.
size() >= 3)
447 jvRequest[jss::issuer] = jvParams[2u].
asString();
450 if (jvParams.
size() >= 4 &&
454 if (jvParams.
size() >= 5)
456 int iLimit = jvParams[5u].
asInt();
459 jvRequest[jss::limit] = iLimit;
462 if (jvParams.
size() >= 6 && jvParams[5u].
asInt())
464 jvRequest[jss::proof] =
true;
467 if (jvParams.
size() == 7)
468 jvRequest[jss::marker] = jvParams[6u];
479 if (!jvParams.
size())
484 jvRequest[
"can_delete"] = jvParams[0u].
asUInt();
486 jvRequest[
"can_delete"] = input;
497 if (jvParams.
size() == 2)
499 jvRequest[jss::ip] = ip;
500 jvRequest[jss::port] = jvParams[1u].
asUInt();
509 jvRequest[jss::port] =
515 jvRequest[jss::ip] = ip;
524 jvRequest[jss::source_account] = jvParams[0u].
asString();
525 jvRequest[jss::destination_account] = jvParams[1u].
asString();
527 if (jvParams.
size() == 3)
546 if (jvParams.
size() > 0)
547 jvRequest[jss::feature] = jvParams[0u].
asString();
549 if (jvParams.
size() > 1)
551 auto const action = jvParams[1u].
asString();
556 if (boost::iequals(action,
"reject"))
558 else if (boost::iequals(action,
"accept"))
574 jvRequest[jss::min_count] = jvParams[0u].
asUInt();
584 bool const bOffline =
585 4 == jvParams.
size() && jvParams[3u].
asString() ==
"offline";
587 if (3 == jvParams.
size() || bOffline)
596 jvRequest[jss::account] = jvParams[0u].
asString();
597 jvRequest[jss::secret] = jvParams[1u].
asString();
598 jvRequest[jss::tx_json] = txJSON;
601 jvRequest[jss::offline] =
true;
616 JLOG(
j_.
trace()) <<
"RPC method: " << jvParams[0u];
617 JLOG(
j_.
trace()) <<
"RPC json: " << jvParams[1u];
624 jvRequest[jss::method] = jvParams[0u];
639 for (
auto const& j : jv)
648 if (jv.
isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0" &&
649 jv.
isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0" &&
667 bool valid_parse = reader.
parse(jvParams[0u].asString(), jv);
675 auto const& params = jv[jss::params];
676 for (
auto i = params.begin(); i != params.end(); ++i)
677 jv1[i.key().asString()] = *i;
679 jv1[jss::jsonrpc] = jv[jss::jsonrpc];
680 jv1[jss::ripplerpc] = jv[jss::ripplerpc];
681 jv1[jss::id] = jv[jss::id];
682 jv1[jss::method] = jv[jss::method];
689 if (jv[j].isMember(jss::params))
691 auto const& params = jv[j][jss::params];
692 for (
auto i = params.begin(); i != params.end(); ++i)
693 jv1[j][i.key().asString()] = *i;
695 jv1[j][jss::jsonrpc] = jv[j][jss::jsonrpc];
696 jv1[j][jss::ripplerpc] = jv[j][jss::ripplerpc];
697 jv1[j][jss::id] = jv[j][jss::id];
698 jv1[j][jss::method] = jv[j][jss::method];
704 jv_error[jss::jsonrpc] = jv[jss::jsonrpc];
706 jv_error[jss::ripplerpc] = jv[jss::ripplerpc];
708 jv_error[jss::id] = jv[jss::id];
718 if (!jvParams.
size())
725 if (2 == jvParams.
size())
727 if (jvParams[1u].asString() ==
"full")
729 jvRequest[jss::full] =
true;
731 else if (jvParams[1u].asString() ==
"tx")
733 jvRequest[jss::transactions] =
true;
734 jvRequest[jss::expand] =
true;
749 if (strLedger.
length() == 64)
751 jvRequest[jss::ledger_hash] = strLedger;
755 jvRequest[jss::ledger_index] =
756 beast::lexicalCast<std::uint32_t>(strLedger);
771 if (jvParams.
size() == 1)
773 jvRequest[jss::severity] = jvParams[0u].
asString();
775 else if (jvParams.
size() == 2)
777 jvRequest[jss::partition] = jvParams[0u].
asString();
778 jvRequest[jss::severity] = jvParams[1u].
asString();
819 unsigned int index = 0;
821 if (jvParams.
size() == 4)
823 jvRequest[jss::passphrase] = jvParams[index];
828 jvRequest[jss::key_type] = jvParams[index];
833 jvRequest[jss::secret] = jvParams[index];
842 jvRequest[jss::channel_id] =
to_string(channelId);
846 if (!jvParams[index].isString() ||
849 jvRequest[jss::amount] = jvParams[index];
868 jvRequest[jss::public_key] = strPk;
875 jvRequest[jss::channel_id] = jvParams[1u].
asString();
877 if (!jvParams[2u].isString() || !
to_uint64(jvParams[2u].asString()))
879 jvRequest[jss::amount] = jvParams[2u];
881 jvRequest[jss::signature] = jvParams[3u].
asString();
890 auto const nParams = jvParams.
size();
892 for (
auto i = 0; i < nParams; ++i)
896 if (i == 1 && strParam.
empty())
902 if (parseBase58<AccountID>(strParam))
904 jvRequest[accFields[i]] = std::move(strParam);
927 unsigned int iCursor = jvParams.
size();
929 if (!parseBase58<AccountID>(strIdent))
935 jvRequest[jss::account] = strIdent;
937 if (iCursor == 2 && !
jvParseLedger(jvRequest, jvParams[1u].asString()))
947 jvRequest[jss::action] = jvParams[0u].
asString();
957 jvRequest[jss::public_key] = jvParams[0u].
asString();
958 if (jvParams.
size() > 1)
960 jvRequest[jss::description] = jvParams[1u].
asString();
970 jvRequest[jss::public_key] = jvParams[0u].
asString();
980 bool bLedger = 2 == jvParams.
size();
982 JLOG(
j_.
trace()) <<
"RPC json: " << jvParams[0u];
1007 bool const bOffline =
1008 3 == jvParams.
size() && jvParams[2u].
asString() ==
"offline";
1010 if (1 == jvParams.
size())
1016 jvRequest[jss::tx_blob] = jvParams[0u].
asString();
1021 (2 == jvParams.
size() || bOffline) &&
1027 jvRequest[jss::secret] = jvParams[0u].
asString();
1028 jvRequest[jss::tx_json] = txJSON;
1031 jvRequest[jss::offline] =
true;
1045 if (1 == jvParams.
size())
1052 jvRequest[jss::tx_json] = txJSON;
1065 assert(jvParams.
size() == 2);
1068 if (txHash.
length() != 64)
1072 jvRequest[jss::tx_hash] = txHash;
1078 if (jvRequest.isMember(jss::ledger_index) &&
1079 jvRequest[jss::ledger_index] == 0)
1091 if (jvParams.
size() == 2 || jvParams.
size() == 4)
1093 if (jvParams[1u].asString() == jss::binary)
1094 jvRequest[jss::binary] =
true;
1097 if (jvParams.
size() >= 3)
1099 const auto offset = jvParams.
size() == 3 ? 0 : 1;
1101 jvRequest[jss::min_ledger] = jvParams[1u + offset].
asString();
1102 jvRequest[jss::max_ledger] = jvParams[2u + offset].
asString();
1105 if (jvParams[0u].asString().length() == 16)
1106 jvRequest[jss::ctid] = jvParams[0u].
asString();
1108 jvRequest[jss::transaction] = jvParams[0u].
asString();
1119 jvRequest[jss::start] = jvParams[0u].
asUInt();
1135 if (jvParams.
size())
1136 jvRequest[jss::secret] = jvParams[0u].
asString();
1149 if (jvParams.
size())
1150 jvRequest[jss::passphrase] = jvParams[0u].
asString();
1162 unsigned int index = 0;
1163 const unsigned int size = jvParams.
size();
1171 if (param[0] !=
'r')
1173 if (param.
size() == 64)
1174 jvRequest[jss::ledger_hash] = param;
1176 jvRequest[jss::ledger_index] = param;
1181 param = jvParams[index++].
asString();
1184 jvRequest[jss::account] = param;
1190 while (index < size)
1191 hotWallets.
append(jvParams[index++].asString());
1203 if (jvParams.
size() == 1)
1205 jvRequest[jss::hash] = jvParams[0u].
asString();
1216 if (jvParams.
size() == 1 && jvParams[0u].
asString() ==
"counters")
1217 jvRequest[jss::counters] =
true;
1236 bool allowAnyCommand)
1240 stream <<
"Method: '" << strMethod <<
"'";
1241 stream <<
"Params: " << jvParams;
1252 static constexpr Command commands[] = {
1300 {
"peer_reservations_add",
1304 {
"peer_reservations_del",
1335 auto const count = jvParams.
size();
1337 for (
auto const& command : commands)
1339 if (strMethod == command.name)
1341 if ((command.minParams >= 0 && count < command.minParams) ||
1342 (command.maxParams >= 0 && count > command.maxParams))
1345 <<
"Wrong number of parameters for " << command.name
1346 <<
" minimum=" << command.minParams
1347 <<
" maximum=" << command.maxParams
1348 <<
" actual=" << count;
1353 return (this->*(command.parse))(jvParams);
1358 if (!allowAnyCommand)
1383 request[jss::method] = strMethod;
1384 request[jss::params] = params;
1385 request[jss::id] = id;
1406 (*jvOutput) = jvInput;
1412 const boost::system::error_code& ecResult,
1423 if (strData.
empty())
1424 Throw<std::runtime_error>(
"no response from server");
1428 if (strData.
find(
"Unable to parse request") == 0 ||
1429 strData.
find(jss::invalid_API_version.c_str()) == 0)
1430 Throw<RequestNotParseable>(strData);
1433 if (!reader.
parse(strData, jvReply))
1434 Throw<std::runtime_error>(
"couldn't parse reply from server");
1437 Throw<std::runtime_error>(
1438 "expected reply to have result, error and id properties");
1442 jvResult[
"result"] = jvReply;
1444 (callbackFuncP)(jvResult);
1457 boost::asio::streambuf& sb,
1461 JLOG(j.
debug()) <<
"requestRPC: strPath='" << strPath <<
"'";
1486 for (
int i = 1; i != args.
size(); i++)
1487 jvRpcParams.
append(args[i]);
1491 retParams[jss::method] = args[0];
1492 retParams[jss::params] = jvRpcParams;
1494 jvRequest = rpParser.
parseCommand(args[0], jvRpcParams,
true);
1497 if (jr.isObject() && !jr.isMember(jss::error) &&
1498 !jr.isMember(jss::api_version))
1505 insert_api_version(jvRequest);
1523 jv[jss::method] = paramsObj.
isMember(jss::method)
1524 ? paramsObj[jss::method].asString()
1528 if (paramsObj.begin() != paramsObj.end())
1531 paramsArray.append(paramsObj);
1533 if (paramsObj.isMember(jss::jsonrpc))
1534 jv[jss::jsonrpc] = paramsObj[jss::jsonrpc];
1535 if (paramsObj.isMember(jss::ripplerpc))
1536 jv[jss::ripplerpc] = paramsObj[jss::ripplerpc];
1537 if (paramsObj.isMember(jss::id))
1538 jv[jss::id] = paramsObj[jss::id];
1553 "Expect specific rpc enum values.");
1566 if (jvRequest.
isMember(jss::error))
1568 jvOutput = jvRequest;
1569 jvOutput[
"rpc"] = jvRpc;
1601 jvParams.
append(jvRequest);
1605 jvParams.
append(jvRequest[i]);
1609 boost::asio::io_service isService;
1619 ? jvRequest[jss::method].
asString()
1620 : jvRequest.
isArray() ?
"batch" : args[0],
1628 std::placeholders::_1),
1636 jvOutput = jvOutput[
"result"];
1647 jvOutput[
"result"] = jvRpcError;
1655 jvOutput[
"request_sent"] =
1662 jvOutput[jss::status] =
"error";
1663 if (jvOutput.
isMember(jss::error_code))
1664 nRet =
std::stoi(jvOutput[jss::error_code].asString());
1665 else if (jvOutput[jss::error].isMember(jss::error_code))
1667 std::stoi(jvOutput[jss::error][jss::error_code].asString());
1675 catch (RequestNotParseable& e)
1678 jvOutput[
"error_what"] = e.what();
1684 jvOutput[
"error_what"] = e.
what();
1688 return {nRet, std::move(jvOutput)};
1701 auto const result =
rpcClient(vCmd, config, logs);
1703 std::cout << result.second.toStyledString();
1705 return result.first;
1712 boost::asio::io_service& io_service,
1726 auto j = logs.
journal(
"HTTPClient");
1731 JLOG(j.info()) << (bSSL ?
"Securely connecting to " :
"Connecting to ")
1736 headers[
"Authorization"] =
1743 constexpr
auto RPC_REPLY_MAX_BYTES =
megabytes(256);
1745 using namespace std::chrono_literals;
1746 auto constexpr RPC_NOTIFY = 10min;
1759 std::placeholders::_1,
1760 std::placeholders::_2,
1762 RPC_REPLY_MAX_BYTES,
1767 std::placeholders::_1,
1768 std::placeholders::_2,
1769 std::placeholders::_3,