mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-01 00:15:51 +00:00
Enable batch rpc processing
* Can be exercised from the command line with json2 * Rewrite Env::do_rpc to call the same code as rpc from the command line. This puts rpc handling logic in one place.
This commit is contained in:
@@ -497,6 +497,17 @@ private:
|
|||||||
|
|
||||||
bool isValidJson2(Json::Value const& jv)
|
bool isValidJson2(Json::Value const& jv)
|
||||||
{
|
{
|
||||||
|
if (jv.isArray())
|
||||||
|
{
|
||||||
|
if (jv.size() == 0)
|
||||||
|
return false;
|
||||||
|
for (auto const& j : jv)
|
||||||
|
{
|
||||||
|
if (!isValidJson2(j))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (jv.isObject())
|
if (jv.isObject())
|
||||||
{
|
{
|
||||||
if (jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0" &&
|
if (jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0" &&
|
||||||
@@ -504,7 +515,7 @@ private:
|
|||||||
jv.isMember(jss::id) && jv.isMember(jss::method))
|
jv.isMember(jss::id) && jv.isMember(jss::method))
|
||||||
{
|
{
|
||||||
if (jv.isMember(jss::params) &&
|
if (jv.isMember(jss::params) &&
|
||||||
!(jv[jss::params].isArray() || jv[jss::params].isNull()))
|
!(jv[jss::params].isArray() || jv[jss::params].isObject()))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -519,17 +530,36 @@ private:
|
|||||||
bool valid_parse = reader.parse(jvParams[0u].asString(), jv);
|
bool valid_parse = reader.parse(jvParams[0u].asString(), jv);
|
||||||
if (valid_parse && isValidJson2(jv))
|
if (valid_parse && isValidJson2(jv))
|
||||||
{
|
{
|
||||||
Json::Value jv1{Json::objectValue};
|
if (jv.isObject())
|
||||||
if (jv.isMember(jss::params))
|
|
||||||
{
|
{
|
||||||
auto const& params = jv[jss::params][0u];
|
Json::Value jv1{Json::objectValue};
|
||||||
for (auto i = params.begin(); i != params.end(); ++i)
|
if (jv.isMember(jss::params))
|
||||||
jv1[i.key().asString()] = *i;
|
{
|
||||||
|
auto const& params = jv[jss::params];
|
||||||
|
for (auto i = params.begin(); i != params.end(); ++i)
|
||||||
|
jv1[i.key().asString()] = *i;
|
||||||
|
}
|
||||||
|
jv1[jss::jsonrpc] = jv[jss::jsonrpc];
|
||||||
|
jv1[jss::ripplerpc] = jv[jss::ripplerpc];
|
||||||
|
jv1[jss::id] = jv[jss::id];
|
||||||
|
jv1[jss::method] = jv[jss::method];
|
||||||
|
return jv1;
|
||||||
|
}
|
||||||
|
// else jv.isArray()
|
||||||
|
Json::Value jv1{Json::arrayValue};
|
||||||
|
for (Json::UInt j = 0; j < jv.size(); ++j)
|
||||||
|
{
|
||||||
|
if (jv[j].isMember(jss::params))
|
||||||
|
{
|
||||||
|
auto const& params = jv[j][jss::params];
|
||||||
|
for (auto i = params.begin(); i != params.end(); ++i)
|
||||||
|
jv1[j][i.key().asString()] = *i;
|
||||||
|
}
|
||||||
|
jv1[j][jss::jsonrpc] = jv[j][jss::jsonrpc];
|
||||||
|
jv1[j][jss::ripplerpc] = jv[j][jss::ripplerpc];
|
||||||
|
jv1[j][jss::id] = jv[j][jss::id];
|
||||||
|
jv1[j][jss::method] = jv[j][jss::method];
|
||||||
}
|
}
|
||||||
jv1[jss::jsonrpc] = jv[jss::jsonrpc];
|
|
||||||
jv1[jss::ripplerpc] = jv[jss::ripplerpc];
|
|
||||||
jv1[jss::id] = jv[jss::id];
|
|
||||||
jv1[jss::method] = jv[jss::method];
|
|
||||||
return jv1;
|
return jv1;
|
||||||
}
|
}
|
||||||
auto jv_error = rpcError(rpcINVALID_PARAMS);
|
auto jv_error = rpcError(rpcINVALID_PARAMS);
|
||||||
@@ -1145,7 +1175,6 @@ struct RPCCallImp
|
|||||||
|
|
||||||
Json::Reader reader;
|
Json::Reader reader;
|
||||||
Json::Value jvReply;
|
Json::Value jvReply;
|
||||||
|
|
||||||
if (!reader.parse (strData, jvReply))
|
if (!reader.parse (strData, jvReply))
|
||||||
Throw<std::runtime_error> ("couldn't parse reply from server");
|
Throw<std::runtime_error> ("couldn't parse reply from server");
|
||||||
|
|
||||||
@@ -1202,7 +1231,6 @@ rpcCmdLineToJson (std::vector<std::string> const& args,
|
|||||||
jvRequest = rpParser.parseCommand (args[0], jvRpcParams, true);
|
jvRequest = rpParser.parseCommand (args[0], jvRpcParams, true);
|
||||||
|
|
||||||
JLOG (j.trace()) << "RPC Request: " << jvRequest << std::endl;
|
JLOG (j.trace()) << "RPC Request: " << jvRequest << std::endl;
|
||||||
|
|
||||||
return jvRequest;
|
return jvRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1287,7 +1315,13 @@ rpcClient(std::vector<std::string> const& args,
|
|||||||
if (!setup.client.admin_password.empty ())
|
if (!setup.client.admin_password.empty ())
|
||||||
jvRequest["admin_password"] = setup.client.admin_password;
|
jvRequest["admin_password"] = setup.client.admin_password;
|
||||||
|
|
||||||
jvParams.append (jvRequest);
|
if (jvRequest.isObject())
|
||||||
|
jvParams.append (jvRequest);
|
||||||
|
else if (jvRequest.isArray())
|
||||||
|
{
|
||||||
|
for (Json::UInt i = 0; i < jvRequest.size(); ++i)
|
||||||
|
jvParams.append(jvRequest[i]);
|
||||||
|
}
|
||||||
|
|
||||||
if (jvRequest.isMember(jss::params))
|
if (jvRequest.isMember(jss::params))
|
||||||
{
|
{
|
||||||
@@ -1305,7 +1339,10 @@ rpcClient(std::vector<std::string> const& args,
|
|||||||
setup.client.password,
|
setup.client.password,
|
||||||
"",
|
"",
|
||||||
jvRequest.isMember (jss::method) // Allow parser to rewrite method.
|
jvRequest.isMember (jss::method) // Allow parser to rewrite method.
|
||||||
? jvRequest[jss::method].asString () : args[0],
|
? jvRequest[jss::method].asString ()
|
||||||
|
: jvRequest.isArray()
|
||||||
|
? "batch"
|
||||||
|
: args[0],
|
||||||
jvParams, // Parsed, execute.
|
jvParams, // Parsed, execute.
|
||||||
setup.client.secure != 0, // Use SSL
|
setup.client.secure != 0, // Use SSL
|
||||||
config.quiet(),
|
config.quiet(),
|
||||||
@@ -1314,7 +1351,6 @@ rpcClient(std::vector<std::string> const& args,
|
|||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
isService.run(); // This blocks until there is no more outstanding async calls.
|
isService.run(); // This blocks until there is no more outstanding async calls.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jvOutput.isMember ("result"))
|
if (jvOutput.isMember ("result"))
|
||||||
{
|
{
|
||||||
// Had a successful JSON-RPC 2.0 call.
|
// Had a successful JSON-RPC 2.0 call.
|
||||||
@@ -1343,10 +1379,12 @@ rpcClient(std::vector<std::string> const& args,
|
|||||||
if (jvOutput.isMember (jss::error))
|
if (jvOutput.isMember (jss::error))
|
||||||
{
|
{
|
||||||
jvOutput[jss::status] = "error";
|
jvOutput[jss::status] = "error";
|
||||||
|
if (jvOutput.isMember(jss::error_code))
|
||||||
nRet = jvOutput.isMember (jss::error_code)
|
nRet = std::stoi(jvOutput[jss::error_code].asString());
|
||||||
? beast::lexicalCast <int> (jvOutput[jss::error_code].asString ())
|
else if (jvOutput[jss::error].isMember(jss::error_code))
|
||||||
: rpcBAD_SYNTAX;
|
nRet = std::stoi(jvOutput[jss::error][jss::error_code].asString());
|
||||||
|
else
|
||||||
|
nRet = rpcBAD_SYNTAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
// YYY We could have a command line flag for single line output for scripts.
|
// YYY We could have a command line flag for single line output for scripts.
|
||||||
@@ -1359,13 +1397,6 @@ rpcClient(std::vector<std::string> const& args,
|
|||||||
nRet = rpcINTERNAL;
|
nRet = rpcINTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jvRequest.isMember(jss::jsonrpc))
|
|
||||||
jvOutput[jss::jsonrpc] = jvRequest[jss::jsonrpc];
|
|
||||||
if (jvRequest.isMember(jss::ripplerpc))
|
|
||||||
jvOutput[jss::ripplerpc] = jvRequest[jss::ripplerpc];
|
|
||||||
if (jvRequest.isMember(jss::id))
|
|
||||||
jvOutput[jss::id] = jvRequest[jss::id];
|
|
||||||
|
|
||||||
return { nRet, std::move(jvOutput) };
|
return { nRet, std::move(jvOutput) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -537,6 +537,22 @@ ServerHandlerImp::processSession (std::shared_ptr<Session> const& session,
|
|||||||
session->close (true);
|
session->close (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
Json::Value
|
||||||
|
make_json_error(Json::Int code, Json::Value&& message)
|
||||||
|
{
|
||||||
|
Json::Value sub{Json::objectValue};
|
||||||
|
sub["code"] = code;
|
||||||
|
sub["message"] = std::move(message);
|
||||||
|
Json::Value r{Json::objectValue};
|
||||||
|
r["error"] = sub;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Int constexpr method_not_found = -32601;
|
||||||
|
Json::Int constexpr server_overloaded = -32604;
|
||||||
|
Json::Int constexpr forbidden = -32605;
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerHandlerImp::processRequest (Port const& port,
|
ServerHandlerImp::processRequest (Port const& port,
|
||||||
std::string const& request, beast::IP::Endpoint const& remoteIPAddress,
|
std::string const& request, beast::IP::Endpoint const& remoteIPAddress,
|
||||||
@@ -545,164 +561,243 @@ ServerHandlerImp::processRequest (Port const& port,
|
|||||||
{
|
{
|
||||||
auto rpcJ = app_.journal ("RPC");
|
auto rpcJ = app_.journal ("RPC");
|
||||||
|
|
||||||
Json::Value jsonRPC;
|
Json::Value jsonOrig;
|
||||||
{
|
{
|
||||||
Json::Reader reader;
|
Json::Reader reader;
|
||||||
if ((request.size () > RPC::Tuning::maxRequestSize) ||
|
if ((request.size () > RPC::Tuning::maxRequestSize) ||
|
||||||
! reader.parse (request, jsonRPC) ||
|
! reader.parse (request, jsonOrig) ||
|
||||||
! jsonRPC ||
|
! jsonOrig ||
|
||||||
! jsonRPC.isObject ())
|
! (jsonOrig.isObject () || jsonOrig.isArray()))
|
||||||
{
|
{
|
||||||
HTTPReply (400, "Unable to parse request", output, rpcJ);
|
HTTPReply (400, "Unable to parse request", output, rpcJ);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
bool batch = false;
|
||||||
// Determine role/usage so we can charge for invalid requests
|
if (jsonOrig.isMember(jss::method) && jsonOrig[jss::method] == "batch")
|
||||||
Json::Value const& method = jsonRPC [jss::method];
|
batch = true;
|
||||||
|
auto size = batch ? jsonOrig[jss::params].size() : 1;
|
||||||
|
Json::Value reply(batch ? Json::arrayValue : Json::objectValue);
|
||||||
|
auto const start (std::chrono::high_resolution_clock::now ());
|
||||||
|
for (unsigned i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
Json::Value const& jsonRPC = batch ? jsonOrig[jss::params][i] : jsonOrig;
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
// Determine role/usage so we can charge for invalid requests
|
||||||
|
Json::Value const& method = jsonRPC [jss::method];
|
||||||
|
|
||||||
auto role = Role::FORBID;
|
auto role = Role::FORBID;
|
||||||
auto required = RPC::roleRequired(method.asString());
|
auto required = RPC::roleRequired(method.asString());
|
||||||
if (jsonRPC.isMember(jss::params) &&
|
if (jsonRPC.isMember(jss::params) &&
|
||||||
jsonRPC[jss::params].isArray() &&
|
jsonRPC[jss::params].isArray() &&
|
||||||
jsonRPC[jss::params].size() > 0 &&
|
jsonRPC[jss::params].size() > 0 &&
|
||||||
jsonRPC[jss::params][Json::UInt(0)].isObject())
|
jsonRPC[jss::params][Json::UInt(0)].isObject())
|
||||||
{
|
|
||||||
role = requestRole(required, port, jsonRPC[jss::params][Json::UInt(0)],
|
|
||||||
remoteIPAddress, user);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
role = requestRole(required, port, Json::objectValue,
|
|
||||||
remoteIPAddress, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
Resource::Consumer usage;
|
|
||||||
if (isUnlimited(role))
|
|
||||||
{
|
|
||||||
usage = m_resourceManager.newUnlimitedEndpoint(
|
|
||||||
remoteIPAddress.to_string());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
usage = m_resourceManager.newInboundEndpoint(remoteIPAddress);
|
|
||||||
if (usage.disconnect())
|
|
||||||
{
|
{
|
||||||
HTTPReply(503, "Server is overloaded", output, rpcJ);
|
role = requestRole(required, port, jsonRPC[jss::params][Json::UInt(0)],
|
||||||
return;
|
remoteIPAddress, user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
role = requestRole(required, port, Json::objectValue,
|
||||||
|
remoteIPAddress, user);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (role == Role::FORBID)
|
Resource::Consumer usage;
|
||||||
{
|
if (isUnlimited(role))
|
||||||
usage.charge(Resource::feeInvalidRPC);
|
{
|
||||||
HTTPReply (403, "Forbidden", output, rpcJ);
|
usage = m_resourceManager.newUnlimitedEndpoint(
|
||||||
return;
|
remoteIPAddress.to_string());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
usage = m_resourceManager.newInboundEndpoint(remoteIPAddress);
|
||||||
|
if (usage.disconnect())
|
||||||
|
{
|
||||||
|
if (!batch)
|
||||||
|
{
|
||||||
|
HTTPReply(503, "Server is overloaded", output, rpcJ);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Json::Value r = jsonRPC;
|
||||||
|
r[jss::error] = make_json_error(server_overloaded, "Server is overloaded");
|
||||||
|
reply.append(r);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (method.isNull())
|
if (role == Role::FORBID)
|
||||||
{
|
|
||||||
usage.charge(Resource::feeInvalidRPC);
|
|
||||||
HTTPReply (400, "Null method", output, rpcJ);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! method.isString ())
|
|
||||||
{
|
|
||||||
usage.charge(Resource::feeInvalidRPC);
|
|
||||||
HTTPReply (400, "method is not string", output, rpcJ);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string strMethod = method.asString ();
|
|
||||||
if (strMethod.empty())
|
|
||||||
{
|
|
||||||
usage.charge(Resource::feeInvalidRPC);
|
|
||||||
HTTPReply (400, "method is empty", output, rpcJ);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract request parameters from the request Json as `params`.
|
|
||||||
//
|
|
||||||
// If the field "params" is empty, `params` is an empty object.
|
|
||||||
//
|
|
||||||
// Otherwise, that field must be an array of length 1 (why?)
|
|
||||||
// and we take that first entry and validate that it's an object.
|
|
||||||
Json::Value params = jsonRPC [jss::params];
|
|
||||||
|
|
||||||
if (! params)
|
|
||||||
params = Json::Value (Json::objectValue);
|
|
||||||
|
|
||||||
else if (!params.isArray () || params.size() != 1)
|
|
||||||
{
|
|
||||||
usage.charge(Resource::feeInvalidRPC);
|
|
||||||
HTTPReply (400, "params unparseable", output, rpcJ);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
params = std::move (params[0u]);
|
|
||||||
if (!params.isObject())
|
|
||||||
{
|
{
|
||||||
usage.charge(Resource::feeInvalidRPC);
|
usage.charge(Resource::feeInvalidRPC);
|
||||||
HTTPReply (400, "params unparseable", output, rpcJ);
|
if (!batch)
|
||||||
return;
|
{
|
||||||
|
HTTPReply (403, "Forbidden", output, rpcJ);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Json::Value r = jsonRPC;
|
||||||
|
r[jss::error] = make_json_error(forbidden, "Forbidden");
|
||||||
|
reply.append(r);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (method.isNull())
|
||||||
|
{
|
||||||
|
usage.charge(Resource::feeInvalidRPC);
|
||||||
|
if (!batch)
|
||||||
|
{
|
||||||
|
HTTPReply (400, "Null method", output, rpcJ);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Json::Value r = jsonRPC;
|
||||||
|
r[jss::error] = make_json_error(method_not_found, "Null method");
|
||||||
|
reply.append(r);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! method.isString ())
|
||||||
|
{
|
||||||
|
usage.charge(Resource::feeInvalidRPC);
|
||||||
|
if (!batch)
|
||||||
|
{
|
||||||
|
HTTPReply (400, "method is not string", output, rpcJ);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Json::Value r = jsonRPC;
|
||||||
|
r[jss::error] = make_json_error(method_not_found, "method is not string");
|
||||||
|
reply.append(r);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string strMethod = method.asString ();
|
||||||
|
if (strMethod.empty())
|
||||||
|
{
|
||||||
|
usage.charge(Resource::feeInvalidRPC);
|
||||||
|
if (!batch)
|
||||||
|
{
|
||||||
|
HTTPReply (400, "method is empty", output, rpcJ);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Json::Value r = jsonRPC;
|
||||||
|
r[jss::error] = make_json_error(method_not_found, "method is empty");
|
||||||
|
reply.append(r);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract request parameters from the request Json as `params`.
|
||||||
|
//
|
||||||
|
// If the field "params" is empty, `params` is an empty object.
|
||||||
|
//
|
||||||
|
// Otherwise, that field must be an array of length 1 (why?)
|
||||||
|
// and we take that first entry and validate that it's an object.
|
||||||
|
Json::Value params;
|
||||||
|
if (!batch)
|
||||||
|
{
|
||||||
|
params = jsonRPC [jss::params];
|
||||||
|
if (! params)
|
||||||
|
params = Json::Value (Json::objectValue);
|
||||||
|
|
||||||
|
else if (!params.isArray () || params.size() != 1)
|
||||||
|
{
|
||||||
|
usage.charge(Resource::feeInvalidRPC);
|
||||||
|
HTTPReply (400, "params unparseable", output, rpcJ);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
params = std::move (params[0u]);
|
||||||
|
if (!params.isObject())
|
||||||
|
{
|
||||||
|
usage.charge(Resource::feeInvalidRPC);
|
||||||
|
HTTPReply (400, "params unparseable", output, rpcJ);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // batch
|
||||||
|
{
|
||||||
|
params = jsonRPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ripplerpc = "1.0";
|
||||||
|
if (params.isMember(jss::ripplerpc) && params[jss::ripplerpc] != "1.0")
|
||||||
|
ripplerpc = params[jss::ripplerpc].asString();
|
||||||
|
/**
|
||||||
|
* Clear header-assigned values if not positively identified from a
|
||||||
|
* secure_gateway.
|
||||||
|
*/
|
||||||
|
if (role != Role::IDENTIFIED)
|
||||||
|
{
|
||||||
|
forwardedFor.clear();
|
||||||
|
user.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
JLOG(m_journal.debug()) << "Query: " << strMethod << params;
|
||||||
|
|
||||||
|
// Provide the JSON-RPC method as the field "command" in the request.
|
||||||
|
params[jss::command] = strMethod;
|
||||||
|
JLOG (m_journal.trace())
|
||||||
|
<< "doRpcCommand:" << strMethod << ":" << params;
|
||||||
|
|
||||||
|
Resource::Charge loadType = Resource::feeReferenceRPC;
|
||||||
|
|
||||||
|
RPC::Context context {m_journal, params, app_, loadType, m_networkOPs,
|
||||||
|
app_.getLedgerMaster(), usage, role, coro, InfoSub::pointer(),
|
||||||
|
{user, forwardedFor}};
|
||||||
|
Json::Value result;
|
||||||
|
RPC::doCommand (context, result);
|
||||||
|
usage.charge (loadType);
|
||||||
|
if (usage.warn())
|
||||||
|
result[jss::warning] = jss::load;
|
||||||
|
|
||||||
|
Json::Value r(Json::objectValue);
|
||||||
|
if (ripplerpc >= "2.0")
|
||||||
|
{
|
||||||
|
if (result.isMember(jss::error))
|
||||||
|
{
|
||||||
|
result[jss::status] = jss::error;
|
||||||
|
result["code"] = result[jss::error_code];
|
||||||
|
result["message"] = result[jss::error_message];
|
||||||
|
result.removeMember(jss::error_message);
|
||||||
|
r[jss::error] = std::move(result);
|
||||||
|
JLOG (m_journal.debug()) <<
|
||||||
|
"rpcError: " << result [jss::error] <<
|
||||||
|
": " << result [jss::error_message];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result[jss::status] = jss::success;
|
||||||
|
r[jss::result] = std::move(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Always report "status". On an error report the request as received.
|
||||||
|
if (result.isMember (jss::error))
|
||||||
|
{
|
||||||
|
result[jss::status] = jss::error;
|
||||||
|
result[jss::request] = params;
|
||||||
|
JLOG (m_journal.debug()) <<
|
||||||
|
"rpcError: " << result [jss::error] <<
|
||||||
|
": " << result [jss::error_message];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result[jss::status] = jss::success;
|
||||||
|
}
|
||||||
|
r[jss::result] = std::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.isMember(jss::jsonrpc))
|
||||||
|
r[jss::jsonrpc] = params[jss::jsonrpc];
|
||||||
|
if (params.isMember(jss::ripplerpc))
|
||||||
|
r[jss::ripplerpc] = params[jss::ripplerpc];
|
||||||
|
if (params.isMember(jss::id))
|
||||||
|
r[jss::id] = params[jss::id];
|
||||||
|
if (batch)
|
||||||
|
reply.append(std::move(r));
|
||||||
|
else
|
||||||
|
reply = std::move(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear header-assigned values if not positively identified from a
|
|
||||||
* secure_gateway.
|
|
||||||
*/
|
|
||||||
if (role != Role::IDENTIFIED)
|
|
||||||
{
|
|
||||||
forwardedFor.clear();
|
|
||||||
user.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
JLOG(m_journal.debug()) << "Query: " << strMethod << params;
|
|
||||||
|
|
||||||
// Provide the JSON-RPC method as the field "command" in the request.
|
|
||||||
params[jss::command] = strMethod;
|
|
||||||
JLOG (m_journal.trace())
|
|
||||||
<< "doRpcCommand:" << strMethod << ":" << params;
|
|
||||||
|
|
||||||
Resource::Charge loadType = Resource::feeReferenceRPC;
|
|
||||||
auto const start (std::chrono::high_resolution_clock::now ());
|
|
||||||
|
|
||||||
RPC::Context context {m_journal, params, app_, loadType, m_networkOPs,
|
|
||||||
app_.getLedgerMaster(), usage, role, coro, InfoSub::pointer(),
|
|
||||||
{user, forwardedFor}};
|
|
||||||
Json::Value result;
|
|
||||||
RPC::doCommand (context, result);
|
|
||||||
|
|
||||||
// Always report "status". On an error report the request as received.
|
|
||||||
if (result.isMember (jss::error))
|
|
||||||
{
|
|
||||||
result[jss::status] = jss::error;
|
|
||||||
result[jss::request] = params;
|
|
||||||
JLOG (m_journal.debug()) <<
|
|
||||||
"rpcError: " << result [jss::error] <<
|
|
||||||
": " << result [jss::error_message];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result[jss::status] = jss::success;
|
|
||||||
}
|
|
||||||
|
|
||||||
usage.charge (loadType);
|
|
||||||
if (usage.warn())
|
|
||||||
result[jss::warning] = jss::load;
|
|
||||||
|
|
||||||
Json::Value reply (Json::objectValue);
|
|
||||||
reply[jss::result] = std::move (result);
|
|
||||||
if (jsonRPC.isMember(jss::jsonrpc))
|
|
||||||
reply[jss::jsonrpc] = jsonRPC[jss::jsonrpc];
|
|
||||||
if (jsonRPC.isMember(jss::ripplerpc))
|
|
||||||
reply[jss::ripplerpc] = jsonRPC[jss::ripplerpc];
|
|
||||||
if (jsonRPC.isMember(jss::id))
|
|
||||||
reply[jss::id] = jsonRPC[jss::id];
|
|
||||||
auto response = to_string (reply);
|
auto response = to_string (reply);
|
||||||
|
|
||||||
rpc_time_.notify (static_cast <beast::insight::Event::value_type> (
|
rpc_time_.notify (static_cast <beast::insight::Event::value_type> (
|
||||||
|
|||||||
@@ -465,31 +465,7 @@ Env::st (JTx const& jt)
|
|||||||
Json::Value
|
Json::Value
|
||||||
Env::do_rpc(std::vector<std::string> const& args)
|
Env::do_rpc(std::vector<std::string> const& args)
|
||||||
{
|
{
|
||||||
auto jv = cmdLineToJSONRPC(args, journal);
|
return rpcClient(args, app().config(), app().logs()).second;
|
||||||
if (!jv.isMember(jss::jsonrpc))
|
|
||||||
{
|
|
||||||
jv[jss::jsonrpc] = "2.0";
|
|
||||||
jv[jss::ripplerpc] = "2.0";
|
|
||||||
jv[jss::id] = 5;
|
|
||||||
}
|
|
||||||
auto response = client().invoke(
|
|
||||||
jv[jss::method].asString(),
|
|
||||||
jv[jss::params][0U]);
|
|
||||||
|
|
||||||
if (jv.isMember(jss::jsonrpc))
|
|
||||||
{
|
|
||||||
response[jss::jsonrpc] = jv[jss::jsonrpc];
|
|
||||||
response[jss::ripplerpc] = jv[jss::ripplerpc];
|
|
||||||
response[jss::id] = jv[jss::id];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jv[jss::params][0u].isMember(jss::error) &&
|
|
||||||
(! response.isMember(jss::error)))
|
|
||||||
{
|
|
||||||
response["client_error"] = jv[jss::params][0u];
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -174,17 +174,17 @@ public:
|
|||||||
"\"ripplerpc\": \"2.0\", "
|
"\"ripplerpc\": \"2.0\", "
|
||||||
"\"id\": 5, "
|
"\"id\": 5, "
|
||||||
"\"method\": \"account_info\", "
|
"\"method\": \"account_info\", "
|
||||||
"\"params\": [{ "
|
"\"params\": { "
|
||||||
"\"account\": \"" + alice.human() + "\"}]}";
|
"\"account\": \"" + alice.human() + "\"}}";
|
||||||
|
|
||||||
auto const withSigners = std::string ("{ ") +
|
auto const withSigners = std::string ("{ ") +
|
||||||
"\"jsonrpc\": \"2.0\", "
|
"\"jsonrpc\": \"2.0\", "
|
||||||
"\"ripplerpc\": \"2.0\", "
|
"\"ripplerpc\": \"2.0\", "
|
||||||
"\"id\": 5, "
|
"\"id\": 6, "
|
||||||
"\"method\": \"account_info\", "
|
"\"method\": \"account_info\", "
|
||||||
"\"params\": [{ "
|
"\"params\": { "
|
||||||
"\"account\": \"" + alice.human() + "\", " +
|
"\"account\": \"" + alice.human() + "\", " +
|
||||||
"\"signer_lists\": true }]}";
|
"\"signer_lists\": true }}";
|
||||||
// Alice has no SignerList yet.
|
// Alice has no SignerList yet.
|
||||||
{
|
{
|
||||||
// account_info without the "signer_lists" argument.
|
// account_info without the "signer_lists" argument.
|
||||||
@@ -209,7 +209,30 @@ public:
|
|||||||
BEAST_EXPECT(signerLists.size() == 0);
|
BEAST_EXPECT(signerLists.size() == 0);
|
||||||
BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
|
||||||
BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
|
BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
|
||||||
BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
|
BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Do both of the above as a batch job
|
||||||
|
auto const info = env.rpc ("json2", '[' + withoutSigners + ", "
|
||||||
|
+ withSigners + ']');
|
||||||
|
BEAST_EXPECT(info[0u].isMember(jss::result) &&
|
||||||
|
info[0u][jss::result].isMember(jss::account_data));
|
||||||
|
BEAST_EXPECT(! info[0u][jss::result][jss::account_data].
|
||||||
|
isMember (jss::signer_lists));
|
||||||
|
BEAST_EXPECT(info[0u].isMember(jss::jsonrpc) && info[0u][jss::jsonrpc] == "2.0");
|
||||||
|
BEAST_EXPECT(info[0u].isMember(jss::ripplerpc) && info[0u][jss::ripplerpc] == "2.0");
|
||||||
|
BEAST_EXPECT(info[0u].isMember(jss::id) && info[0u][jss::id] == 5);
|
||||||
|
|
||||||
|
BEAST_EXPECT(info[1u].isMember(jss::result) &&
|
||||||
|
info[1u][jss::result].isMember(jss::account_data));
|
||||||
|
auto const& data = info[1u][jss::result][jss::account_data];
|
||||||
|
BEAST_EXPECT(data.isMember (jss::signer_lists));
|
||||||
|
auto const& signerLists = data[jss::signer_lists];
|
||||||
|
BEAST_EXPECT(signerLists.isArray());
|
||||||
|
BEAST_EXPECT(signerLists.size() == 0);
|
||||||
|
BEAST_EXPECT(info[1u].isMember(jss::jsonrpc) && info[1u][jss::jsonrpc] == "2.0");
|
||||||
|
BEAST_EXPECT(info[1u].isMember(jss::ripplerpc) && info[1u][jss::ripplerpc] == "2.0");
|
||||||
|
BEAST_EXPECT(info[1u].isMember(jss::id) && info[1u][jss::id] == 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give alice a SignerList.
|
// Give alice a SignerList.
|
||||||
@@ -247,7 +270,7 @@ public:
|
|||||||
BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
|
BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
|
||||||
BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
|
||||||
BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
|
BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
|
||||||
BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
|
BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give alice a big signer list
|
// Give alice a big signer list
|
||||||
@@ -287,7 +310,7 @@ public:
|
|||||||
}
|
}
|
||||||
BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
|
||||||
BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
|
BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
|
||||||
BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
|
BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -374,7 +374,7 @@ public:
|
|||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5)"
|
R"("id" : 5)"
|
||||||
" }");
|
" }");
|
||||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
BEAST_EXPECT(lines[jss::error][jss::message] ==
|
||||||
RPC::missing_field_error(jss::account)[jss::error_message]);
|
RPC::missing_field_error(jss::account)[jss::error_message]);
|
||||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||||
@@ -387,10 +387,10 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": )"
|
R"({"account": )"
|
||||||
R"("n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"}]})");
|
R"("n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"}})");
|
||||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
BEAST_EXPECT(lines[jss::error][jss::message] ==
|
||||||
RPC::make_error(rpcBAD_SEED)[jss::error_message]);
|
RPC::make_error(rpcBAD_SEED)[jss::error_message]);
|
||||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||||
@@ -404,9 +404,9 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"("}]})");
|
R"({"account": ")" + alice.human() + R"("}})");
|
||||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
BEAST_EXPECT(lines[jss::error][jss::message] ==
|
||||||
RPC::make_error(rpcACT_NOT_FOUND)[jss::error_message]);
|
RPC::make_error(rpcACT_NOT_FOUND)[jss::error_message]);
|
||||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||||
@@ -424,8 +424,8 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"("}]})");
|
R"({"account": ")" + alice.human() + R"("}})");
|
||||||
BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
|
BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
|
||||||
BEAST_EXPECT(lines[jss::result][jss::lines].size() == 0);
|
BEAST_EXPECT(lines[jss::result][jss::lines].size() == 0);
|
||||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||||
@@ -439,10 +439,10 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("ledger_index": "nonsense"}]})");
|
R"("ledger_index": "nonsense"}})");
|
||||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
BEAST_EXPECT(lines[jss::error][jss::message] ==
|
||||||
"ledgerIndexMalformed");
|
"ledgerIndexMalformed");
|
||||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||||
@@ -455,10 +455,10 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("ledger_index": 50000}]})");
|
R"("ledger_index": 50000}})");
|
||||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
BEAST_EXPECT(lines[jss::error][jss::message] ==
|
||||||
"ledgerNotFound");
|
"ledgerNotFound");
|
||||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||||
@@ -525,9 +525,9 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + account.human() + R"(", )"
|
R"({"account": ")" + account.human() + R"(", )"
|
||||||
R"("ledger_index": )" + std::to_string(info.seq) + "}]}");
|
R"("ledger_index": )" + std::to_string(info.seq) + "}}");
|
||||||
BEAST_EXPECT(linesSeq[jss::result][jss::lines].isArray());
|
BEAST_EXPECT(linesSeq[jss::result][jss::lines].isArray());
|
||||||
BEAST_EXPECT(linesSeq[jss::result][jss::lines].size() == count);
|
BEAST_EXPECT(linesSeq[jss::result][jss::lines].size() == count);
|
||||||
BEAST_EXPECT(linesSeq.isMember(jss::jsonrpc) && linesSeq[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(linesSeq.isMember(jss::jsonrpc) && linesSeq[jss::jsonrpc] == "2.0");
|
||||||
@@ -540,9 +540,9 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + account.human() + R"(", )"
|
R"({"account": ")" + account.human() + R"(", )"
|
||||||
R"("ledger_hash": ")" + to_string(info.hash) + R"("}]})");
|
R"("ledger_hash": ")" + to_string(info.hash) + R"("}})");
|
||||||
BEAST_EXPECT(linesHash[jss::result][jss::lines].isArray());
|
BEAST_EXPECT(linesHash[jss::result][jss::lines].isArray());
|
||||||
BEAST_EXPECT(linesHash[jss::result][jss::lines].size() == count);
|
BEAST_EXPECT(linesHash[jss::result][jss::lines].size() == count);
|
||||||
BEAST_EXPECT(linesHash.isMember(jss::jsonrpc) && linesHash[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(linesHash.isMember(jss::jsonrpc) && linesHash[jss::jsonrpc] == "2.0");
|
||||||
@@ -567,10 +567,10 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("ledger_hash": ")" + to_string(ledger4Info.hash) + R"(", )"
|
R"("ledger_hash": ")" + to_string(ledger4Info.hash) + R"(", )"
|
||||||
R"("ledger_index": )" + std::to_string(ledger58Info.seq) + "}]}");
|
R"("ledger_index": )" + std::to_string(ledger58Info.seq) + "}}");
|
||||||
BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
|
BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
|
||||||
BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
|
BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
|
||||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||||
@@ -584,8 +584,8 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"("}]})");
|
R"({"account": ")" + alice.human() + R"("}})");
|
||||||
BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
|
BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
|
||||||
BEAST_EXPECT(lines[jss::result][jss::lines].size() == 52);
|
BEAST_EXPECT(lines[jss::result][jss::lines].size() == 52);
|
||||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||||
@@ -599,9 +599,9 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("peer": ")" + gw1.human() + R"("}]})");
|
R"("peer": ")" + gw1.human() + R"("}})");
|
||||||
BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
|
BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
|
||||||
BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
|
BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
|
||||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||||
@@ -615,11 +615,11 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("peer": )"
|
R"("peer": )"
|
||||||
R"("n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"}]})");
|
R"("n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"}})");
|
||||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
BEAST_EXPECT(lines[jss::error][jss::message] ==
|
||||||
RPC::make_error(rpcBAD_SEED)[jss::error_message]);
|
RPC::make_error(rpcBAD_SEED)[jss::error_message]);
|
||||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||||
@@ -632,10 +632,10 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("limit": -1}]})");
|
R"("limit": -1}})");
|
||||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
BEAST_EXPECT(lines[jss::error][jss::message] ==
|
||||||
RPC::expected_field_message(jss::limit, "unsigned integer"));
|
RPC::expected_field_message(jss::limit, "unsigned integer"));
|
||||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||||
@@ -648,9 +648,9 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("limit": 1}]})");
|
R"("limit": 1}})");
|
||||||
BEAST_EXPECT(linesA[jss::result][jss::lines].isArray());
|
BEAST_EXPECT(linesA[jss::result][jss::lines].isArray());
|
||||||
BEAST_EXPECT(linesA[jss::result][jss::lines].size() == 1);
|
BEAST_EXPECT(linesA[jss::result][jss::lines].size() == 1);
|
||||||
BEAST_EXPECT(linesA.isMember(jss::jsonrpc) && linesA[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(linesA.isMember(jss::jsonrpc) && linesA[jss::jsonrpc] == "2.0");
|
||||||
@@ -664,9 +664,9 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("marker": ")" + marker + R"("}]})");
|
R"("marker": ")" + marker + R"("}})");
|
||||||
BEAST_EXPECT(linesB[jss::result][jss::lines].isArray());
|
BEAST_EXPECT(linesB[jss::result][jss::lines].isArray());
|
||||||
BEAST_EXPECT(linesB[jss::result][jss::lines].size() == 51);
|
BEAST_EXPECT(linesB[jss::result][jss::lines].size() == 51);
|
||||||
BEAST_EXPECT(linesB.isMember(jss::jsonrpc) && linesB[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(linesB.isMember(jss::jsonrpc) && linesB[jss::jsonrpc] == "2.0");
|
||||||
@@ -679,10 +679,10 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("limit": 3, )"
|
R"("limit": 3, )"
|
||||||
R"("marker": ")" + marker + R"("}]})");
|
R"("marker": ")" + marker + R"("}})");
|
||||||
BEAST_EXPECT(linesC[jss::result][jss::lines].isArray());
|
BEAST_EXPECT(linesC[jss::result][jss::lines].isArray());
|
||||||
BEAST_EXPECT(linesC[jss::result][jss::lines].size() == 3);
|
BEAST_EXPECT(linesC[jss::result][jss::lines].size() == 3);
|
||||||
BEAST_EXPECT(linesC.isMember(jss::jsonrpc) && linesC[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(linesC.isMember(jss::jsonrpc) && linesC[jss::jsonrpc] == "2.0");
|
||||||
@@ -696,10 +696,10 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("marker": ")" + marker + R"("}]})");
|
R"("marker": ")" + marker + R"("}})");
|
||||||
BEAST_EXPECT(linesD[jss::result][jss::error_message] ==
|
BEAST_EXPECT(linesD[jss::error][jss::message] ==
|
||||||
RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]);
|
RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]);
|
||||||
BEAST_EXPECT(linesD.isMember(jss::jsonrpc) && linesD[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(linesD.isMember(jss::jsonrpc) && linesD[jss::jsonrpc] == "2.0");
|
||||||
BEAST_EXPECT(linesD.isMember(jss::ripplerpc) && linesD[jss::ripplerpc] == "2.0");
|
BEAST_EXPECT(linesD.isMember(jss::ripplerpc) && linesD[jss::ripplerpc] == "2.0");
|
||||||
@@ -712,10 +712,10 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("marker": true}]})");
|
R"("marker": true}})");
|
||||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
BEAST_EXPECT(lines[jss::error][jss::message] ==
|
||||||
RPC::expected_field_message(jss::marker, "string"));
|
RPC::expected_field_message(jss::marker, "string"));
|
||||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||||
@@ -728,10 +728,10 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("limit": 1, )"
|
R"("limit": 1, )"
|
||||||
R"("peer": ")" + gw2.human() + R"("}]})");
|
R"("peer": ")" + gw2.human() + R"("}})");
|
||||||
auto const& line = lines[jss::result][jss::lines][0u];
|
auto const& line = lines[jss::result][jss::lines][0u];
|
||||||
BEAST_EXPECT(line[jss::freeze].asBool() == true);
|
BEAST_EXPECT(line[jss::freeze].asBool() == true);
|
||||||
BEAST_EXPECT(line[jss::no_ripple].asBool() == true);
|
BEAST_EXPECT(line[jss::no_ripple].asBool() == true);
|
||||||
@@ -747,10 +747,10 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + gw2.human() + R"(", )"
|
R"({"account": ")" + gw2.human() + R"(", )"
|
||||||
R"("limit": 1, )"
|
R"("limit": 1, )"
|
||||||
R"("peer": ")" + alice.human() + R"("}]})");
|
R"("peer": ")" + alice.human() + R"("}})");
|
||||||
auto const& lineA = linesA[jss::result][jss::lines][0u];
|
auto const& lineA = linesA[jss::result][jss::lines][0u];
|
||||||
BEAST_EXPECT(lineA[jss::freeze_peer].asBool() == true);
|
BEAST_EXPECT(lineA[jss::freeze_peer].asBool() == true);
|
||||||
BEAST_EXPECT(lineA[jss::no_ripple_peer].asBool() == true);
|
BEAST_EXPECT(lineA[jss::no_ripple_peer].asBool() == true);
|
||||||
@@ -767,11 +767,11 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + gw2.human() + R"(", )"
|
R"({"account": ")" + gw2.human() + R"(", )"
|
||||||
R"("limit": 25, )"
|
R"("limit": 25, )"
|
||||||
R"("marker": ")" + marker + R"(", )"
|
R"("marker": ")" + marker + R"(", )"
|
||||||
R"("peer": ")" + alice.human() + R"("}]})");
|
R"("peer": ")" + alice.human() + R"("}})");
|
||||||
BEAST_EXPECT(linesB[jss::result][jss::lines].isArray());
|
BEAST_EXPECT(linesB[jss::result][jss::lines].isArray());
|
||||||
BEAST_EXPECT(linesB[jss::result][jss::lines].size() == 25);
|
BEAST_EXPECT(linesB[jss::result][jss::lines].size() == 25);
|
||||||
BEAST_EXPECT(! linesB[jss::result].isMember(jss::marker));
|
BEAST_EXPECT(! linesB[jss::result].isMember(jss::marker));
|
||||||
@@ -833,9 +833,9 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("limit": 1}]})");
|
R"("limit": 1}})");
|
||||||
BEAST_EXPECT(linesBeg[jss::result][jss::lines][0u][jss::currency] == "USD");
|
BEAST_EXPECT(linesBeg[jss::result][jss::lines][0u][jss::currency] == "USD");
|
||||||
BEAST_EXPECT(linesBeg[jss::result].isMember(jss::marker));
|
BEAST_EXPECT(linesBeg[jss::result].isMember(jss::marker));
|
||||||
BEAST_EXPECT(linesBeg.isMember(jss::jsonrpc) && linesBeg[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(linesBeg.isMember(jss::jsonrpc) && linesBeg[jss::jsonrpc] == "2.0");
|
||||||
@@ -853,11 +853,11 @@ public:
|
|||||||
R"("jsonrpc" : "2.0",)"
|
R"("jsonrpc" : "2.0",)"
|
||||||
R"("ripplerpc" : "2.0",)"
|
R"("ripplerpc" : "2.0",)"
|
||||||
R"("id" : 5,)"
|
R"("id" : 5,)"
|
||||||
R"("params": [ )"
|
R"("params": )"
|
||||||
R"({"account": ")" + alice.human() + R"(", )"
|
R"({"account": ")" + alice.human() + R"(", )"
|
||||||
R"("marker": ")" +
|
R"("marker": ")" +
|
||||||
linesBeg[jss::result][jss::marker].asString() + R"("}]})");
|
linesBeg[jss::result][jss::marker].asString() + R"("}})");
|
||||||
BEAST_EXPECT(linesEnd[jss::result][jss::error_message] ==
|
BEAST_EXPECT(linesEnd[jss::error][jss::message] ==
|
||||||
RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]);
|
RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]);
|
||||||
BEAST_EXPECT(linesEnd.isMember(jss::jsonrpc) && linesEnd[jss::jsonrpc] == "2.0");
|
BEAST_EXPECT(linesEnd.isMember(jss::jsonrpc) && linesEnd[jss::jsonrpc] == "2.0");
|
||||||
BEAST_EXPECT(linesEnd.isMember(jss::ripplerpc) && linesEnd[jss::ripplerpc] == "2.0");
|
BEAST_EXPECT(linesEnd.isMember(jss::ripplerpc) && linesEnd[jss::ripplerpc] == "2.0");
|
||||||
|
|||||||
@@ -122,9 +122,9 @@ public:
|
|||||||
|
|
||||||
// test error on no account
|
// test error on no account
|
||||||
{
|
{
|
||||||
auto resp = env.rpc("account_objects");
|
auto resp = env.rpc("json", "account_objects");
|
||||||
BEAST_EXPECT( resp[jss::result][jss::error_message] ==
|
BEAST_EXPECT( resp[jss::error_message] ==
|
||||||
"Missing field 'account'.");
|
"Syntax error.");
|
||||||
}
|
}
|
||||||
// test error on malformed account string.
|
// test error on malformed account string.
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -197,10 +197,10 @@ public:
|
|||||||
|
|
||||||
{
|
{
|
||||||
// no account field
|
// no account field
|
||||||
auto const jrr = env.rpc ("account_offers")[jss::result];
|
auto const jrr = env.rpc ("account_offers");
|
||||||
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
BEAST_EXPECT(jrr[jss::error] == "badSyntax");
|
||||||
BEAST_EXPECT(jrr[jss::status] == "error");
|
BEAST_EXPECT(jrr[jss::status] == "error");
|
||||||
BEAST_EXPECT(jrr[jss::error_message] == "Missing field 'account'.");
|
BEAST_EXPECT(jrr[jss::error_message] == "Syntax error.");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -250,10 +250,8 @@ class Feature_test : public beast::unit_test::suite
|
|||||||
|
|
||||||
// anything other than accept or reject is an error
|
// anything other than accept or reject is an error
|
||||||
jrr = env.rpc("feature", "CryptoConditions", "maybe");
|
jrr = env.rpc("feature", "CryptoConditions", "maybe");
|
||||||
if(! BEAST_EXPECT(jrr.isMember("client_error")))
|
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
|
||||||
return;
|
BEAST_EXPECT(jrr[jss::error_message] == "Invalid parameters.");
|
||||||
BEAST_EXPECT(jrr["client_error"][jss::error] == "invalidParams");
|
|
||||||
BEAST_EXPECT(jrr["client_error"][jss::error_message] == "Invalid parameters.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -73,16 +73,16 @@ public:
|
|||||||
|
|
||||||
{
|
{
|
||||||
Env env(*this);
|
Env env(*this);
|
||||||
auto const result = env.rpc("server_info", "1");
|
auto const result = env.rpc("server_info");
|
||||||
BEAST_EXPECT(!result[jss::result].isMember (jss::error));
|
BEAST_EXPECT(!result[jss::result].isMember (jss::error));
|
||||||
BEAST_EXPECT(result[jss::status] == "success");
|
BEAST_EXPECT(result[jss::result][jss::status] == "success");
|
||||||
BEAST_EXPECT(result[jss::result].isMember(jss::info));
|
BEAST_EXPECT(result[jss::result].isMember(jss::info));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Env env(*this, makeValidatorConfig());
|
Env env(*this, makeValidatorConfig());
|
||||||
auto const result = env.rpc("server_info", "1");
|
auto const result = env.rpc("server_info");
|
||||||
BEAST_EXPECT(!result[jss::result].isMember (jss::error));
|
BEAST_EXPECT(!result[jss::result].isMember (jss::error));
|
||||||
BEAST_EXPECT(result[jss::status] == "success");
|
BEAST_EXPECT(result[jss::result][jss::status] == "success");
|
||||||
BEAST_EXPECT(result[jss::result].isMember(jss::info));
|
BEAST_EXPECT(result[jss::result].isMember(jss::info));
|
||||||
BEAST_EXPECT(result[jss::result][jss::info]
|
BEAST_EXPECT(result[jss::result][jss::info]
|
||||||
[jss::pubkey_validator] == validator_data::public_key);
|
[jss::pubkey_validator] == validator_data::public_key);
|
||||||
|
|||||||
@@ -786,7 +786,7 @@ class ServerStatus_test :
|
|||||||
using namespace beast::http;
|
using namespace beast::http;
|
||||||
Env env {*this, validator( envconfig([](std::unique_ptr<Config> cfg)
|
Env env {*this, validator( envconfig([](std::unique_ptr<Config> cfg)
|
||||||
{
|
{
|
||||||
cfg->section("port_rpc").set("protocol", "http,https");
|
cfg->section("port_rpc").set("protocol", "http");
|
||||||
return cfg;
|
return cfg;
|
||||||
}), "")};
|
}), "")};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user