Cleanups to RPC code

This commit is contained in:
Tom Ritchford
2014-08-03 18:42:00 -04:00
committed by Nik Bougalis
parent 4c7fd18230
commit 22ca13bc78
35 changed files with 402 additions and 477 deletions

View File

@@ -2725,6 +2725,9 @@
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ripple\module\rpc\handlers\Handlers.h"> <ClInclude Include="..\..\src\ripple\module\rpc\handlers\Handlers.h">
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ripple\module\rpc\handlers\Internal.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\module\rpc\handlers\Ledger.cpp"> <ClCompile Include="..\..\src\ripple\module\rpc\handlers\Ledger.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild> <ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile> </ClCompile>
@@ -2773,9 +2776,6 @@
<ClCompile Include="..\..\src\ripple\module\rpc\handlers\Print.cpp"> <ClCompile Include="..\..\src\ripple\module\rpc\handlers\Print.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild> <ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\ripple\module\rpc\handlers\Profile.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\module\rpc\handlers\ProofCreate.cpp"> <ClCompile Include="..\..\src\ripple\module\rpc\handlers\ProofCreate.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild> <ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile> </ClCompile>
@@ -2921,6 +2921,8 @@
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ripple\module\rpc\impl\TransactionSign.h"> <ClInclude Include="..\..\src\ripple\module\rpc\impl\TransactionSign.h">
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\module\rpc\InternalHandler.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\module\rpc\Manager.h"> <ClInclude Include="..\..\src\ripple\module\rpc\Manager.h">
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\module\rpc\Request.h"> <ClInclude Include="..\..\src\ripple\module\rpc\Request.h">

View File

@@ -3888,6 +3888,9 @@
<ClInclude Include="..\..\src\ripple\module\rpc\handlers\Handlers.h"> <ClInclude Include="..\..\src\ripple\module\rpc\handlers\Handlers.h">
<Filter>ripple\module\rpc\handlers</Filter> <Filter>ripple\module\rpc\handlers</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ripple\module\rpc\handlers\Internal.cpp">
<Filter>ripple\module\rpc\handlers</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\module\rpc\handlers\Ledger.cpp"> <ClCompile Include="..\..\src\ripple\module\rpc\handlers\Ledger.cpp">
<Filter>ripple\module\rpc\handlers</Filter> <Filter>ripple\module\rpc\handlers</Filter>
</ClCompile> </ClCompile>
@@ -3936,9 +3939,6 @@
<ClCompile Include="..\..\src\ripple\module\rpc\handlers\Print.cpp"> <ClCompile Include="..\..\src\ripple\module\rpc\handlers\Print.cpp">
<Filter>ripple\module\rpc\handlers</Filter> <Filter>ripple\module\rpc\handlers</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\ripple\module\rpc\handlers\Profile.cpp">
<Filter>ripple\module\rpc\handlers</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\module\rpc\handlers\ProofCreate.cpp"> <ClCompile Include="..\..\src\ripple\module\rpc\handlers\ProofCreate.cpp">
<Filter>ripple\module\rpc\handlers</Filter> <Filter>ripple\module\rpc\handlers</Filter>
</ClCompile> </ClCompile>
@@ -4095,6 +4095,9 @@
<ClInclude Include="..\..\src\ripple\module\rpc\impl\TransactionSign.h"> <ClInclude Include="..\..\src\ripple\module\rpc\impl\TransactionSign.h">
<Filter>ripple\module\rpc\impl</Filter> <Filter>ripple\module\rpc\impl</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\module\rpc\InternalHandler.h">
<Filter>ripple\module\rpc</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\module\rpc\Manager.h"> <ClInclude Include="..\..\src\ripple\module\rpc\Manager.h">
<Filter>ripple\module\rpc</Filter> <Filter>ripple\module\rpc</Filter>
</ClInclude> </ClInclude>

View File

@@ -74,7 +74,7 @@ public:
if (! getConfig ().getRpcIP().empty () && if (! getConfig ().getRpcIP().empty () &&
getConfig ().getRpcPort() != 0) getConfig ().getRpcPort() != 0)
{ {
beast::IP::Endpoint ep (beast::IP::Endpoint::from_string (getConfig().getRpcIP())); auto ep = beast::IP::Endpoint::from_string (getConfig().getRpcIP());
// VFALCO TODO IP address should not have an "unspecified" state // VFALCO TODO IP address should not have an "unspecified" state
//if (! is_unspecified (ep)) //if (! is_unspecified (ep))
@@ -143,18 +143,11 @@ public:
return; return;
} }
#if 0
// Synchronous version that doesn't use job queue
Job job;
processSession (job, session);
#else
session.detach(); session.detach();
m_jobQueue.addJob (jtCLIENT, "RPC-Client", std::bind ( m_jobQueue.addJob (jtCLIENT, "RPC-Client", std::bind (
&RPCHTTPServerImp::processSession, this, std::placeholders::_1, &RPCHTTPServerImp::processSession, this, std::placeholders::_1,
std::ref (session))); std::ref (session)));
#endif
} }
void void
@@ -174,15 +167,9 @@ public:
// Dispatched on the job queue // Dispatched on the job queue
void processSession (Job& job, HTTP::Session& session) void processSession (Job& job, HTTP::Session& session)
{ {
#if 0
// Goes through the old code
session.write (m_deprecatedHandler.processRequest (
session.content(), session.remoteAddress().at_port(0)));
#else
auto const s (to_string(session.message().body)); auto const s (to_string(session.message().body));
session.write (processRequest (to_string(session.message().body), session.write (processRequest (to_string(session.message().body),
session.remoteAddress().at_port(0))); session.remoteAddress().at_port(0)));
#endif
if (session.message().keep_alive()) if (session.message().keep_alive())
{ {
@@ -219,7 +206,7 @@ public:
} }
} }
Config::Role const role (getConfig ().getAdminRole (jvRequest, remoteIPAddress)); auto const role = getConfig ().getAdminRole (jvRequest, remoteIPAddress);
Resource::Consumer usage; Resource::Consumer usage;
@@ -233,34 +220,30 @@ public:
// Parse id now so errors from here on will have the id // Parse id now so errors from here on will have the id
// //
// VFALCO NOTE Except that "id" isn't included in the following errors... // VFALCO NOTE Except that "id" isn't included in the following errors.
// //
Json::Value const id = jvRequest ["id"]; Json::Value const id = jvRequest ["id"];
Json::Value const method = jvRequest ["method"]; Json::Value const method = jvRequest ["method"];
if (method.isNull ()) if (method.isNull ())
{
return createResponse (400, "Null method"); return createResponse (400, "Null method");
}
else if (! method.isString ()) if (! method.isString ())
{
return createResponse (400, "method is not string"); return createResponse (400, "method is not string");
}
std::string strMethod = method.asString (); std::string strMethod = method.asString ();
if (strMethod.empty())
return createResponse (400, "method is empty");
// Parse params // Parse params
Json::Value params = jvRequest ["params"]; Json::Value params = jvRequest ["params"];
if (params.isNull ()) if (params.isNull ())
{
params = Json::Value (Json::arrayValue); params = Json::Value (Json::arrayValue);
}
else if (!params.isArray ()) else if (!params.isArray ())
{
return HTTPReply (400, "params unparseable"); return HTTPReply (400, "params unparseable");
}
// VFALCO TODO Shouldn't we handle this earlier? // VFALCO TODO Shouldn't we handle this earlier?
// //
@@ -272,20 +255,19 @@ public:
return HTTPReply (403, "Forbidden"); return HTTPReply (403, "Forbidden");
} }
std::string response; std::string response;
RPCHandler rpcHandler (m_networkOPs);
Resource::Charge loadType = Resource::feeReferenceRPC;
m_journal.debug << "Query: " << strMethod << params; m_journal.debug << "Query: " << strMethod << params;
RPCHandler rpcHandler (m_networkOPs);
Resource::Charge loadType = Resource::feeReferenceRPC;
Json::Value const result (rpcHandler.doRpcCommand ( Json::Value const result (rpcHandler.doRpcCommand (
strMethod, params, role, loadType)); strMethod, params, role, loadType));
m_journal.debug << "Reply: " << result;
usage.charge (loadType); usage.charge (loadType);
m_journal.debug << "Reply: " << result;
response = JSONRPCReply (result, Json::Value (), id); response = JSONRPCReply (result, Json::Value (), id);
@@ -314,8 +296,11 @@ RPCHTTPServer::RPCHTTPServer (Stoppable& parent)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
std::unique_ptr <RPCHTTPServer> std::unique_ptr <RPCHTTPServer>
make_RPCHTTPServer (beast::Stoppable& parent, beast::Journal journal, make_RPCHTTPServer (
JobQueue& jobQueue, NetworkOPs& networkOPs, beast::Stoppable& parent,
beast::Journal journal,
JobQueue& jobQueue,
NetworkOPs& networkOPs,
Resource::Manager& resourceManager) Resource::Manager& resourceManager)
{ {
return std::make_unique <RPCHTTPServerImp> ( return std::make_unique <RPCHTTPServerImp> (

View File

@@ -0,0 +1,50 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_APP_RPC_INTERNAL_HANDLER
#define RIPPLE_APP_RPC_INTERNAL_HANDLER
namespace ripple {
namespace RPC {
/** To dynamically add custom or experimental RPC handlers, construct a new
* instance of InternalHandler with your own handler function. */
struct InternalHandler
{
typedef Json::Value (*handler_t) (const Json::Value&);
InternalHandler (const std::string& name, handler_t handler)
: name_ (name),
handler_ (handler)
{
nextHandler_ = InternalHandler::headHandler;
InternalHandler::headHandler = this;
}
InternalHandler* nextHandler_;
std::string name_;
handler_t handler_;
static InternalHandler* headHandler;
};
} // RPC
} // ripple
#endif

View File

@@ -34,7 +34,6 @@ public:
virtual ~Manager () = 0; virtual ~Manager () = 0;
/** Add a handler for the specified JSON-RPC command. */ /** Add a handler for the specified JSON-RPC command. */
/** @{ */
template <class Handler> template <class Handler>
void add (std::string const& method) void add (std::string const& method)
{ {
@@ -47,17 +46,16 @@ public:
} }
virtual void add (std::string const& method, handler_type&& handler) = 0; virtual void add (std::string const& method, handler_type&& handler) = 0;
/** @} */
/** Dispatch the JSON-RPC request. /** Dispatch the JSON-RPC request.
@return `true` If the command was found. @return `true` if the command was found.
*/ */
virtual bool dispatch (Request& req) = 0; virtual bool dispatch (Request& req) = 0;
}; };
std::unique_ptr <Manager> make_Manager (beast::Journal journal); std::unique_ptr <Manager> make_Manager (beast::Journal journal);
} } // RPC
} } // ripple
#endif #endif

View File

@@ -32,52 +32,31 @@
namespace ripple { namespace ripple {
// used by the RPCServer or WSDoor to carry out these RPC commands // used by the RPCServer or WSDoor to carry out these RPC commands
class NetworkOPs;
class InfoSub; class InfoSub;
class NetworkOPs;
class RPCHandler class RPCHandler
{ {
public: public:
explicit RPCHandler (NetworkOPs& netOps); explicit RPCHandler (
NetworkOPs& netOps, InfoSub::pointer infoSub = nullptr);
RPCHandler (NetworkOPs& netOps, InfoSub::pointer infoSub);
Json::Value doCommand ( Json::Value doCommand (
Json::Value const& jvRequest, Config::Role role, Json::Value const& request,
Config::Role role,
Resource::Charge& loadType); Resource::Charge& loadType);
Json::Value doRpcCommand ( Json::Value doRpcCommand (
std::string const& strCommand, Json::Value const& jvParams, std::string const& command,
Config::Role iRole, Resource::Charge& loadType); Json::Value const& params,
Config::Role role,
// Utilities Resource::Charge& loadType);
private: private:
NetworkOPs* mNetOps; NetworkOPs& netOps_;
InfoSub::pointer mInfoSub; InfoSub::pointer infoSub_;
Config::Role mRole; Config::Role role_ = Config::FORBID;
};
class RPCInternalHandler
{
public:
typedef Json::Value (*handler_t) (Json::Value const&);
public:
RPCInternalHandler (std::string const& name, handler_t handler);
static Json::Value runHandler (
std::string const& name, Json::Value const& params);
private:
// VFALCO TODO Replace with a singleton with a well defined interface and
// a lock free stack (if necessary).
//
static RPCInternalHandler* sHeadHandler;
RPCInternalHandler* mNextHandler;
std::string mName;
handler_t mHandler;
}; };
} // ripple } // ripple

View File

@@ -29,13 +29,13 @@ class NetworkOPs;
class RPCServerHandler : public RPCServer::Handler class RPCServerHandler : public RPCServer::Handler
{ {
public: public:
explicit RPCServerHandler (NetworkOPs& networkOPs, Resource::Manager& resourceManager); RPCServerHandler (NetworkOPs&, Resource::Manager&);
std::string createResponse (int statusCode, std::string const& description); std::string createResponse (int statusCode, std::string const& description);
bool isAuthorized (std::map <std::string, std::string> const& headers); bool isAuthorized (std::map <std::string, std::string> const& headers);
std::string processRequest (std::string const& request, std::string processRequest (
std::string const& request,
beast::IP::Endpoint const& remoteIPAddress); beast::IP::Endpoint const& remoteIPAddress);
private: private:

View File

@@ -23,17 +23,18 @@
#include <ripple/unity/json.h> #include <ripple/unity/json.h>
#include <ripple/unity/resource.h> #include <ripple/unity/resource.h>
namespace ripple { namespace ripple {
class Application; // forward declare class Application;
namespace RPC { namespace RPC {
struct Request struct Request
{ {
explicit Request (beast::Journal journal_, explicit Request (
std::string const& method_, Json::Value& params_, beast::Journal journal_,
std::string const& method_,
Json::Value& params_,
Application& app_) Application& app_)
: journal (journal_) : journal (journal_)
, method (method_) , method (method_)

View File

@@ -28,8 +28,7 @@ const int MAX_PATHFINDS_IN_PROGRESS = 2;
const int MAX_PATHFIND_JOB_COUNT = 50; const int MAX_PATHFIND_JOB_COUNT = 50;
const int MAX_JOB_QUEUE_CLIENTS = 500; const int MAX_JOB_QUEUE_CLIENTS = 500;
const int MAX_VALIDATED_LEDGER_AGE = 120; const int MAX_VALIDATED_LEDGER_AGE = 120;
const int MAX_REQUEST_SIZE = 1000000;
// TODO(tom): Shouldn't DEFAULT_AUTO_FILL_FEE_MULTIPLIER be floating point?
} // RPC } // RPC
} // ripple } // ripple

View File

@@ -22,10 +22,13 @@ namespace ripple {
// { // {
// account: <indent>, // account: <indent>,
// account_index : <index> // optional // account_index : <index> // optional
// strict: <bool> // true, only allow public keys and addresses. false, default. // strict: <bool>
// if true, only allow public keys and addresses. false, default.
// ledger_hash : <ledger> // ledger_hash : <ledger>
// ledger_index : <ledger_index> // ledger_index : <ledger_index>
// } // }
// TODO(tom): what is that "default"?
Json::Value doAccountInfo (RPC::Context& context) Json::Value doAccountInfo (RPC::Context& context)
{ {
auto& params = context.params_; auto& params = context.params_;

View File

@@ -73,10 +73,11 @@ Json::Value doAccountOffers (RPC::Context& context)
return rpcError (rpcACT_NOT_FOUND); return rpcError (rpcACT_NOT_FOUND);
Json::Value& jvsOffers = (result[jss::offers] = Json::arrayValue); Json::Value& jvsOffers = (result[jss::offers] = Json::arrayValue);
ledger->visitAccountItems (raAccount.getAccountID (), auto adder = std::bind (
std::bind (&offerAdder, std::ref (jvsOffers), &offerAdder,
std::placeholders::_1)); std::ref (jvsOffers),
std::placeholders::_1);
ledger->visitAccountItems (raAccount.getAccountID (), adder);
context.loadType_ = Resource::feeMediumBurdenRPC; context.loadType_ = Resource::feeMediumBurdenRPC;
return result; return result;

View File

@@ -53,7 +53,6 @@ Json::Value doPathFind (RPC::Context&);
Json::Value doPeers (RPC::Context&); Json::Value doPeers (RPC::Context&);
Json::Value doPing (RPC::Context&); Json::Value doPing (RPC::Context&);
Json::Value doPrint (RPC::Context&); Json::Value doPrint (RPC::Context&);
Json::Value doProfile (RPC::Context&);
Json::Value doProofCreate (RPC::Context&); Json::Value doProofCreate (RPC::Context&);
Json::Value doProofSolve (RPC::Context&); Json::Value doProofSolve (RPC::Context&);
Json::Value doProofVerify (RPC::Context&); Json::Value doProofVerify (RPC::Context&);

View File

@@ -0,0 +1,53 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012-2014 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <ripple/module/rpc/InternalHandler.h>
namespace ripple {
RPC::InternalHandler* RPC::InternalHandler::headHandler = nullptr;
Json::Value doInternal (RPC::Context& context)
{
// Used for debug or special-purpose RPC commands
if (!context.params_.isMember ("internal_command"))
return rpcError (rpcINVALID_PARAMS);
auto name = context.params_["internal_command"].asString ();
auto params = context.params_["params"];
for (auto* h = RPC::InternalHandler::headHandler; h; )
{
if (name == h->name_)
{
WriteLog (lsWARNING, RPCHandler)
<< "Internal command " << name << ": " << params;
Json::Value ret = h->handler_ (params);
WriteLog (lsWARNING, RPCHandler)
<< "Internal command returns: " << ret;
return ret;
}
h = h->nextHandler_;
}
return rpcError (rpcBAD_SYNTAX);
}
} // ripple

View File

@@ -22,13 +22,11 @@ namespace ripple {
Json::Value doLedgerClosed (RPC::Context& context) Json::Value doLedgerClosed (RPC::Context& context)
{ {
Json::Value jvResult;
uint256 uLedger = context.netOps_.getClosedLedgerHash (); uint256 uLedger = context.netOps_.getClosedLedgerHash ();
Json::Value jvResult;
jvResult["ledger_index"] = context.netOps_.getLedgerID (uLedger); jvResult["ledger_index"] = context.netOps_.getLedgerID (uLedger);
jvResult["ledger_hash"] = to_string (uLedger); jvResult["ledger_hash"] = to_string (uLedger);
//jvResult["ledger_time"] = uLedger.
return jvResult; return jvResult;
} }

View File

@@ -23,9 +23,7 @@ namespace ripple {
Json::Value doLedgerCurrent (RPC::Context& context) Json::Value doLedgerCurrent (RPC::Context& context)
{ {
Json::Value jvResult; Json::Value jvResult;
jvResult["ledger_current_index"] = context.netOps_.getCurrentLedgerID (); jvResult["ledger_current_index"] = context.netOps_.getCurrentLedgerID ();
return jvResult; return jvResult;
} }

View File

@@ -24,12 +24,14 @@ namespace ripple {
// 'ident' : <indent>, // 'ident' : <indent>,
// 'account_index' : <index> // optional // 'account_index' : <index> // optional
// } // }
// XXX This would be better if it took the ledger.
Json::Value doOwnerInfo (RPC::Context& context) Json::Value doOwnerInfo (RPC::Context& context)
{ {
auto lock = getApp().masterLock(); auto lock = getApp().masterLock();
if (!context.params_.isMember ("account") && !context.params_.isMember ("ident")) if (!context.params_.isMember ("account") &&
!context.params_.isMember ("ident"))
{
return RPC::missing_field_error ("account"); return RPC::missing_field_error ("account");
}
std::string strIdent = context.params_.isMember ("account") std::string strIdent = context.params_.isMember ("account")
? context.params_["account"].asString () ? context.params_["account"].asString ()
@@ -38,25 +40,35 @@ Json::Value doOwnerInfo (RPC::Context& context)
int iIndex = context.params_.isMember ("account_index") int iIndex = context.params_.isMember ("account_index")
? context.params_["account_index"].asUInt () : 0; ? context.params_["account_index"].asUInt () : 0;
RippleAddress raAccount; RippleAddress raAccount;
Json::Value ret; Json::Value ret;
// Get info on account. // Get info on account.
auto const& closedLedger = context.netOps_.getClosedLedger ();
Json::Value jAccepted = RPC::accountFromString ( Json::Value jAccepted = RPC::accountFromString (
context.netOps_.getClosedLedger (), raAccount, bIndex, strIdent, iIndex, closedLedger,
false, context.netOps_); raAccount,
bIndex,
strIdent,
iIndex,
false,
context.netOps_);
ret["accepted"] = jAccepted.empty () ret["accepted"] = jAccepted.empty () ? context.netOps_.getOwnerInfo (
? context.netOps_.getOwnerInfo ( closedLedger, raAccount) : jAccepted;
context.netOps_.getClosedLedger (), raAccount) : jAccepted;
auto const& currentLedger = context.netOps_.getCurrentLedger ();
Json::Value jCurrent = RPC::accountFromString ( Json::Value jCurrent = RPC::accountFromString (
context.netOps_.getCurrentLedger (), raAccount, bIndex, strIdent, iIndex, currentLedger,
false, context.netOps_); raAccount,
bIndex,
strIdent,
iIndex,
false,
context.netOps_);
ret["current"] = jCurrent.empty () ? context.netOps_.getOwnerInfo ( ret["current"] = jCurrent.empty () ? context.netOps_.getOwnerInfo (
context.netOps_.getCurrentLedger (), raAccount) : jCurrent; currentLedger, raAccount) : jCurrent;
return ret; return ret;
} }

View File

@@ -1,120 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012-2014 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
// profile offers <pass_a> <account_a> <currency_offer_a> <account_b>
// <currency_offer_b> <count> [submit]
//
// profile 0:offers 1:pass_a 2:account_a 3:currency_offer_a 4:account_b
// 5:currency_offer_b 6:<count> 7:[submit]
//
// issuer is the offering account
//
// --> submit: 'submit|true|false': defaults to false
//
// Prior to running allow each to have a credit line of what they will be
// getting from the other account.
Json::Value doProfile (RPC::Context& context)
{
/* need to fix now that sharedOfferCreate is gone
int iArgs = context.params_.size();
RippleAddress naSeedA;
RippleAddress naAccountA;
Currency uCurrencyOfferA;
RippleAddress naSeedB;
RippleAddress naAccountB;
Currency uCurrencyOfferB;
uint32 iCount = 100;
bool bSubmit = false;
if (iArgs < 6 || "offers" != context.params_[0u].asString())
{
return rpcError(rpcINVALID_PARAMS);
}
if (!naSeedA.setSeedGeneric(context.params_[1u].asString())) // <pass_a>
return rpcError(rpcINVALID_PARAMS);
naAccountA.setAccountID(context.params_[2u].asString()); // <account_a>
if (!to_currency(uCurrencyOfferA, context.params_[3u].asString())) // <currency_offer_a>
return rpcError(rpcINVALID_PARAMS);
naAccountB.setAccountID(context.params_[4u].asString()); // <account_b>
if (!to_currency(uCurrencyOfferB, context.params_[5u].asString())) // <currency_offer_b>
return rpcError(rpcINVALID_PARAMS);
iCount = lexicalCast <uint32>(context.params_[6u].asString());
if (iArgs >= 8 && "false" != context.params_[7u].asString())
bSubmit = true;
boost::posix_time::ptime ptStart(boost::posix_time::microsec_clock::local_time());
for(unsigned int n=0; n<iCount; n++)
{
RippleAddress naMasterGeneratorA;
RippleAddress naAccountPublicA;
RippleAddress naAccountPrivateA;
AccountState::pointer asSrcA;
STAmount saSrcBalanceA;
Json::Value jvObjA = authorize(uint256(0), naSeedA, naAccountA, naAccountPublicA, naAccountPrivateA,
saSrcBalanceA, getConfig ().FEE_DEFAULT, asSrcA, naMasterGeneratorA);
if (!jvObjA.empty())
return jvObjA;
Transaction::pointer tpOfferA = Transaction::sharedOfferCreate(
naAccountPublicA, naAccountPrivateA,
naAccountA, // naSourceAccount,
asSrcA->getSeq(), // uSeq
getConfig ().FEE_DEFAULT,
0, // uSourceTag,
false, // bPassive
STAmount(uCurrencyOfferA, naAccountA.getAccountID(), 1), // saTakerPays
STAmount(uCurrencyOfferB, naAccountB.getAccountID(), 1+n), // saTakerGets
0); // uExpiration
if (bSubmit)
tpOfferA = context.netOps_.submitTransactionSync(tpOfferA); // FIXME: Don't use synch interface
}
boost::posix_time::ptime ptEnd(boost::posix_time::microsec_clock::local_time());
boost::posix_time::time_duration tdInterval = ptEnd-ptStart;
long lMicroseconds = tdInterval.total_microseconds();
int iTransactions = iCount;
float fRate = lMicroseconds ? iTransactions/(lMicroseconds/1000000.0) : 0.0;
Json::Value obj(Json::objectValue);
obj["transactions"] = iTransactions;
obj["submit"] = bSubmit;
obj["start"] = boost::posix_time::to_simple_string(ptStart);
obj["end"] = boost::posix_time::to_simple_string(ptEnd);
obj["interval"] = boost::posix_time::to_simple_string(tdInterval);
obj["rate_per_second"] = fRate;
*/
Json::Value obj (Json::objectValue);
return obj;
}
} // ripple

View File

@@ -60,7 +60,7 @@ Json::Value doProofVerify (RPC::Context& context)
if (iDifficulty < 0 || if (iDifficulty < 0 ||
iDifficulty > ProofOfWorkFactory::kMaxDifficulty) iDifficulty > ProofOfWorkFactory::kMaxDifficulty)
{ {
return RPC::missing_field_error ("difficulty"); return RPC::invalid_field_error ("difficulty");
} }
pgGen->setDifficulty (iDifficulty); pgGen->setDifficulty (iDifficulty);

View File

@@ -26,10 +26,11 @@ namespace ripple {
// } // }
Json::Value doRandom (RPC::Context& context) Json::Value doRandom (RPC::Context& context)
{ {
uint256 rand; // TODO(tom): the try/catch is almost certainly redundant, we catch at the
// top level too.
try try
{ {
uint256 rand;
RandomNumbers::getInstance ().fillBytes (rand.begin (), rand.size ()); RandomNumbers::getInstance ().fillBytes (rand.begin (), rand.size ());
Json::Value jvResult; Json::Value jvResult;

View File

@@ -30,8 +30,10 @@ namespace ripple {
Json::Value doTransactionEntry (RPC::Context& context) Json::Value doTransactionEntry (RPC::Context& context)
{ {
Ledger::pointer lpLedger; Ledger::pointer lpLedger;
Json::Value jvResult Json::Value jvResult = RPC::lookupLedger (
= RPC::lookupLedger (context.params_, lpLedger, context.netOps_); context.params_,
lpLedger,
context.netOps_);
if (!lpLedger) if (!lpLedger)
return jvResult; return jvResult;

View File

@@ -44,6 +44,7 @@ Json::Value doTx (RPC::Context& context)
return rpcError (rpcTXN_NOT_FOUND); return rpcError (rpcTXN_NOT_FOUND);
#ifdef READY_FOR_NEW_TX_FORMAT #ifdef READY_FOR_NEW_TX_FORMAT
// TODO(tom): what new format is this?
Json::Value ret; Json::Value ret;
ret[jss::transaction] = txn->getJson (0, binary); ret[jss::transaction] = txn->getJson (0, binary);
#else #else
@@ -52,12 +53,9 @@ Json::Value doTx (RPC::Context& context)
if (txn->getLedger () != 0) if (txn->getLedger () != 0)
{ {
auto lgr = context.netOps_.getLedgerBySeq (txn->getLedger ()); if (auto lgr = context.netOps_.getLedgerBySeq (txn->getLedger ()))
if (lgr)
{ {
bool okay = false; bool okay = false;
if (binary) if (binary)
{ {
std::string meta; std::string meta;
@@ -71,7 +69,6 @@ Json::Value doTx (RPC::Context& context)
else else
{ {
TransactionMetaSet::pointer set; TransactionMetaSet::pointer set;
if (lgr->getTransactionMeta (txid, set)) if (lgr->getTransactionMeta (txid, set))
{ {
okay = true; okay = true;

View File

@@ -39,14 +39,12 @@ Json::Value doUnlAdd (RPC::Context& context)
{ {
getApp().getUNL ().nodeAddPublic ( getApp().getUNL ().nodeAddPublic (
raNodePublic, UniqueNodeList::vsManual, strComment); raNodePublic, UniqueNodeList::vsManual, strComment);
return "adding node by public key"; return "adding node by public key";
} }
else else
{ {
getApp().getUNL ().nodeAddDomain ( getApp().getUNL ().nodeAddDomain (
strNode, UniqueNodeList::vsManual, strComment); strNode, UniqueNodeList::vsManual, strComment);
return "adding node by domain"; return "adding node by domain";
} }
} }

View File

@@ -30,20 +30,17 @@ Json::Value doUnlDelete (RPC::Context& context)
if (!context.params_.isMember ("node")) if (!context.params_.isMember ("node"))
return rpcError (rpcINVALID_PARAMS); return rpcError (rpcINVALID_PARAMS);
std::string strNode = context.params_["node"].asString (); auto strNode = context.params_["node"].asString ();
RippleAddress raNodePublic; RippleAddress raNodePublic;
if (raNodePublic.setNodePublic (strNode)) if (raNodePublic.setNodePublic (strNode))
{ {
getApp().getUNL ().nodeRemovePublic (raNodePublic); getApp().getUNL ().nodeRemovePublic (raNodePublic);
return "removing node by public key"; return "removing node by public key";
} }
else else
{ {
getApp().getUNL ().nodeRemoveDomain (strNode); getApp().getUNL ().nodeRemoveDomain (strNode);
return "removing node by domain"; return "removing node by domain";
} }
} }

View File

@@ -41,7 +41,6 @@ Json::Value doUnsubscribe (RPC::Context& context)
return rpcError (rpcNO_PERMISSION); return rpcError (rpcNO_PERMISSION);
std::string strUrl = context.params_["url"].asString (); std::string strUrl = context.params_["url"].asString ();
ispSub = context.netOps_.findRpcSub (strUrl); ispSub = context.netOps_.findRpcSub (strUrl);
if (!ispSub) if (!ispSub)
@@ -116,44 +115,40 @@ Json::Value doUnsubscribe (RPC::Context& context)
} }
else else
{ {
for (auto& jvSubRequest: context.params_["books"]) for (auto& jv: context.params_["books"])
{ {
if (!jvSubRequest.isObject () if (!jv.isObject ()
|| !jvSubRequest.isMember ("taker_pays") || !jv.isMember ("taker_pays")
|| !jvSubRequest.isMember ("taker_gets") || !jv.isMember ("taker_gets")
|| !jvSubRequest["taker_pays"].isObject () || !jv["taker_pays"].isObject ()
|| !jvSubRequest["taker_gets"].isObject ()) || !jv["taker_gets"].isObject ())
return rpcError (rpcINVALID_PARAMS); return rpcError (rpcINVALID_PARAMS);
Currency pay_currency; bool bBoth = (jv.isMember ("both") && jv["both"].asBool ()) ||
Account pay_issuer; (jv.isMember ("both_sides") && jv["both_sides"].asBool ());
Currency get_currency; // both_sides is deprecated.
Account get_issuer;
bool bBoth = (jvSubRequest.isMember ("both") &&
jvSubRequest["both"].asBool ())
|| (jvSubRequest.isMember ("both_sides") &&
jvSubRequest["both_sides"].asBool ()); // DEPRECATED
Json::Value taker_pays = jvSubRequest["taker_pays"]; Json::Value taker_pays = jv["taker_pays"];
Json::Value taker_gets = jvSubRequest["taker_gets"]; Json::Value taker_gets = jv["taker_gets"];
Book book;
// Parse mandatory currency. // Parse mandatory currency.
if (!taker_pays.isMember ("currency") if (!taker_pays.isMember ("currency")
|| !to_currency ( || !to_currency (
pay_currency, taker_pays["currency"].asString ())) book.in.currency, taker_pays["currency"].asString ()))
{ {
WriteLog (lsINFO, RPCHandler) << "Bad taker_pays currency."; WriteLog (lsINFO, RPCHandler) << "Bad taker_pays currency.";
return rpcError (rpcSRC_CUR_MALFORMED); return rpcError (rpcSRC_CUR_MALFORMED);
} }
// Parse optional issuer. // Parse optional issuer.
else if (((taker_pays.isMember ("issuer")) else if (((taker_pays.isMember ("issuer"))
&& (!taker_pays["issuer"].isString () && (!taker_pays["issuer"].isString ()
|| !to_issuer ( || !to_issuer (
pay_issuer, taker_pays["issuer"].asString ()))) book.in.account, taker_pays["issuer"].asString ())))
// Don't allow illegal issuers. // Don't allow illegal issuers.
|| (!pay_currency != !pay_issuer) || !isConsistent (book.in)
|| noAccount() == pay_issuer) || noAccount() == book.in.account)
{ {
WriteLog (lsINFO, RPCHandler) << "Bad taker_pays issuer."; WriteLog (lsINFO, RPCHandler) << "Bad taker_pays issuer.";
@@ -162,7 +157,7 @@ Json::Value doUnsubscribe (RPC::Context& context)
// Parse mandatory currency. // Parse mandatory currency.
if (!taker_gets.isMember ("currency") if (!taker_gets.isMember ("currency")
|| !to_currency (get_currency, || !to_currency (book.out.currency,
taker_gets["currency"].asString ())) taker_gets["currency"].asString ()))
{ {
WriteLog (lsINFO, RPCHandler) << "Bad taker_pays currency."; WriteLog (lsINFO, RPCHandler) << "Bad taker_pays currency.";
@@ -172,26 +167,24 @@ Json::Value doUnsubscribe (RPC::Context& context)
// Parse optional issuer. // Parse optional issuer.
else if (((taker_gets.isMember ("issuer")) else if (((taker_gets.isMember ("issuer"))
&& (!taker_gets["issuer"].isString () && (!taker_gets["issuer"].isString ()
|| !to_issuer (get_issuer, || !to_issuer (book.out.account,
taker_gets["issuer"].asString ()))) taker_gets["issuer"].asString ())))
// Don't allow illegal issuers. // Don't allow illegal issuers.
|| (!get_currency != !get_issuer) || !isConsistent (book.out)
|| noAccount() == get_issuer) || noAccount() == book.out.account)
{ {
WriteLog (lsINFO, RPCHandler) << "Bad taker_gets issuer."; WriteLog (lsINFO, RPCHandler) << "Bad taker_gets issuer.";
return rpcError (rpcDST_ISR_MALFORMED); return rpcError (rpcDST_ISR_MALFORMED);
} }
if (pay_currency == get_currency if (book.in == book.out)
&& pay_issuer == get_issuer)
{ {
WriteLog (lsINFO, RPCHandler) << "taker_gets same as taker_pays."; WriteLog (lsINFO, RPCHandler)
<< "taker_gets same as taker_pays.";
return rpcError (rpcBAD_MARKET); return rpcError (rpcBAD_MARKET);
} }
Book book{{pay_currency, pay_issuer}, {get_currency, get_issuer}};
context.netOps_.unsubBook (ispSub->getSeq (), book); context.netOps_.unsubBook (ispSub->getSeq (), book);
if (bBoth) if (bBoth)

View File

@@ -25,65 +25,66 @@ namespace RPC {
// --> strIdent: public key, account ID, or regular seed. // --> strIdent: public key, account ID, or regular seed.
// --> bStrict: Only allow account id or public key. // --> bStrict: Only allow account id or public key.
// <-- bIndex: true if iIndex > 0 and used the index. // <-- bIndex: true if iIndex > 0 and used the index.
Json::Value accountFromString (Ledger::ref lrLedger, RippleAddress& naAccount, Json::Value accountFromString (
bool& bIndex, std::string const& strIdent, Ledger::ref lrLedger,
const int iIndex, const bool bStrict, NetworkOPs& netOps) RippleAddress& naAccount,
bool& bIndex,
std::string const& strIdent,
int const iIndex,
bool const bStrict,
NetworkOPs& netOps)
{ {
RippleAddress naSeed; RippleAddress naSeed;
if (naAccount.setAccountPublic (strIdent) || naAccount.setAccountID (strIdent)) if (naAccount.setAccountPublic (strIdent) ||
naAccount.setAccountID (strIdent))
{ {
// Got the account. // Got the account.
bIndex = false; bIndex = false;
return Json::Value (Json::objectValue);
} }
else if (bStrict)
if (bStrict)
{ {
return naAccount.setAccountID (strIdent, Base58::getBitcoinAlphabet ()) auto success = naAccount.setAccountID (
? rpcError (rpcACT_BITCOIN) strIdent, Base58::getBitcoinAlphabet ());
: rpcError (rpcACT_MALFORMED); return rpcError (success ? rpcACT_BITCOIN : rpcACT_MALFORMED);
} }
// Must be a seed.
else if (!naSeed.setSeedGeneric (strIdent)) // Otherwise, it must be a seed.
{ if (!naSeed.setSeedGeneric (strIdent))
return rpcError (rpcBAD_SEED); return rpcError (rpcBAD_SEED);
}
else
{
// We allow the use of the seeds to access #0. // We allow the use of the seeds to access #0.
// This is poor practice and merely for debuging convenience. // This is poor practice and merely for debugging convenience.
RippleAddress naRegular0Public; RippleAddress naRegular0Public;
RippleAddress naRegular0Private; RippleAddress naRegular0Private;
RippleAddress naGenerator = RippleAddress::createGeneratorPublic (naSeed); auto naGenerator = RippleAddress::createGeneratorPublic (naSeed);
naRegular0Public.setAccountPublic (naGenerator, 0); naRegular0Public.setAccountPublic (naGenerator, 0);
naRegular0Private.setAccountPrivate (naGenerator, naSeed, 0); naRegular0Private.setAccountPrivate (naGenerator, naSeed, 0);
// Account uGeneratorID = naRegular0Public.getAccountID(); SLE::pointer sleGen = netOps.getGenerator (
SLE::pointer sleGen = netOps.getGenerator (lrLedger, naRegular0Public.getAccountID ()); lrLedger, naRegular0Public.getAccountID ());
if (!sleGen) if (sleGen)
{
// Didn't find a generator map, assume it is a master generator.
}
else
{ {
// Found master public key. // Found master public key.
Blob vucCipher = sleGen->getFieldVL (sfGenerator); Blob vucCipher = sleGen->getFieldVL (sfGenerator);
Blob vucMasterGenerator = naRegular0Private.accountPrivateDecrypt (naRegular0Public, vucCipher); Blob vucMasterGenerator = naRegular0Private.accountPrivateDecrypt (
naRegular0Public, vucCipher);
if (vucMasterGenerator.empty ()) if (vucMasterGenerator.empty ())
{
rpcError (rpcNO_GEN_DECRYPT); rpcError (rpcNO_GEN_DECRYPT);
}
naGenerator.setGenerator (vucMasterGenerator); naGenerator.setGenerator (vucMasterGenerator);
} }
// Otherwise, if we didn't find a generator map, assume it is a master
// generator.
bIndex = !iIndex; bIndex = !iIndex;
naAccount.setAccountPublic (naGenerator, iIndex); naAccount.setAccountPublic (naGenerator, iIndex);
}
return Json::Value (Json::objectValue); return Json::Value (Json::objectValue);
} }

View File

@@ -40,7 +40,8 @@ public:
void add (std::string const& method, handler_type&& handler) void add (std::string const& method, handler_type&& handler)
{ {
m_map.emplace (std::piecewise_construct, std::forward_as_tuple (method), m_map.emplace (std::piecewise_construct,
std::forward_as_tuple (method),
std::forward_as_tuple (std::move (handler))); std::forward_as_tuple (std::move (handler)));
} }
@@ -63,7 +64,6 @@ Manager::~Manager ()
std::unique_ptr <Manager> make_Manager (beast::Journal journal) std::unique_ptr <Manager> make_Manager (beast::Journal journal)
{ {
std::unique_ptr <Manager> m (std::make_unique <ManagerImp> (journal)); std::unique_ptr <Manager> m (std::make_unique <ManagerImp> (journal));
m->add <DoPrint> ("print"); m->add <DoPrint> ("print");
return m; return m;

View File

@@ -24,24 +24,21 @@ namespace RPC {
hash_set<RippleAddress> parseAccountIds (Json::Value const& jvArray) hash_set<RippleAddress> parseAccountIds (Json::Value const& jvArray)
{ {
hash_set<RippleAddress> usnaResult; hash_set<RippleAddress> result;
for (Json::Value::const_iterator it = jvArray.begin (); it != jvArray.end (); it++) for (auto const& jv: jvArray)
{ {
RippleAddress naString; RippleAddress address;
if (! (*it).isString () || !naString.setAccountID ((*it).asString ())) if (!(jv.isString () && address.setAccountID ((jv.asString ()))))
{ {
usnaResult.clear (); result.clear ();
break; break;
} }
else result.insert (address);
{
(void) usnaResult.insert (naString);
}
} }
return usnaResult; return result;
} }
} // RPC } // RPC

View File

@@ -27,23 +27,10 @@
namespace ripple { namespace ripple {
//
// Carries out the RPC.
//
RPCHandler::RPCHandler (NetworkOPs& netOps)
: mNetOps (&netOps)
, mRole (Config::FORBID)
{
assert (mNetOps);
}
RPCHandler::RPCHandler (NetworkOPs& netOps, InfoSub::pointer infoSub) RPCHandler::RPCHandler (NetworkOPs& netOps, InfoSub::pointer infoSub)
: mNetOps (&netOps) : netOps_ (netOps)
, mInfoSub (infoSub) , infoSub_ (infoSub)
, mRole (Config::FORBID)
{ {
assert (mNetOps);
} }
// Provide the JSON-RPC "result" value. // Provide the JSON-RPC "result" value.
@@ -52,8 +39,10 @@ RPCHandler::RPCHandler (NetworkOPs& netOps, InfoSub::pointer infoSub)
// transport for a command and a request object. The command is the method. The // transport for a command and a request object. The command is the method. The
// request object is supplied as the first element of the params. // request object is supplied as the first element of the params.
Json::Value RPCHandler::doRpcCommand ( Json::Value RPCHandler::doRpcCommand (
std::string const& strMethod, Json::Value const& jvParams, const std::string& strMethod,
Config::Role iRole, Resource::Charge& loadType) Json::Value const& jvParams,
Config::Role role,
Resource::Charge& loadType)
{ {
WriteLog (lsTRACE, RPCHandler) WriteLog (lsTRACE, RPCHandler)
<< "doRpcCommand:" << strMethod << ":" << jvParams; << "doRpcCommand:" << strMethod << ":" << jvParams;
@@ -70,7 +59,7 @@ Json::Value RPCHandler::doRpcCommand (
// Provide the JSON-RPC method as the field "command" in the request. // Provide the JSON-RPC method as the field "command" in the request.
params[jss::command] = strMethod; params[jss::command] = strMethod;
Json::Value jvResult = doCommand (params, iRole, loadType); Json::Value jvResult = doCommand (params, role, loadType);
// Always report "status". On an error report the request as received. // Always report "status". On an error report the request as received.
if (jvResult.isMember ("error")) if (jvResult.isMember ("error"))
@@ -86,22 +75,12 @@ Json::Value RPCHandler::doRpcCommand (
return logRPCError (jvResult); return logRPCError (jvResult);
} }
// TODO(tom): this should go with the other handlers.
Json::Value doInternal (RPC::Context& context)
{
// Used for debug or special-purpose RPC commands
if (!context.params_.isMember ("internal_command"))
return rpcError (rpcINVALID_PARAMS);
return RPCInternalHandler::runHandler (
context.params_["internal_command"].asString (),
context.params_["params"]);
}
Json::Value RPCHandler::doCommand ( Json::Value RPCHandler::doCommand (
Json::Value const& params, Config::Role iRole, Resource::Charge& loadType) const Json::Value& params,
Config::Role role,
Resource::Charge& loadType)
{ {
if (iRole != Config::ADMIN) if (role != Config::ADMIN)
{ {
// VFALCO NOTE Should we also add up the jtRPC jobs? // VFALCO NOTE Should we also add up the jtRPC jobs?
// //
@@ -121,22 +100,22 @@ Json::Value RPCHandler::doCommand (
WriteLog (lsTRACE, RPCHandler) << "COMMAND:" << strCommand; WriteLog (lsTRACE, RPCHandler) << "COMMAND:" << strCommand;
WriteLog (lsTRACE, RPCHandler) << "REQUEST:" << params; WriteLog (lsTRACE, RPCHandler) << "REQUEST:" << params;
mRole = iRole; role_ = role;
const RPC::Handler* handler = RPC::getHandler(strCommand); auto handler = RPC::getHandler(strCommand);
if (!handler) if (!handler)
return rpcError (rpcUNKNOWN_COMMAND); return rpcError (rpcUNKNOWN_COMMAND);
if (handler->role_ == Config::ADMIN && mRole != Config::ADMIN) if (handler->role_ == Config::ADMIN && role_ != Config::ADMIN)
return rpcError (rpcNO_PERMISSION); return rpcError (rpcNO_PERMISSION);
if ((handler->condition_ & RPC::NEEDS_NETWORK_CONNECTION) && if ((handler->condition_ & RPC::NEEDS_NETWORK_CONNECTION) &&
(mNetOps->getOperatingMode () < NetworkOPs::omSYNCING)) (netOps_.getOperatingMode () < NetworkOPs::omSYNCING))
{ {
WriteLog (lsINFO, RPCHandler) WriteLog (lsINFO, RPCHandler)
<< "Insufficient network mode for RPC: " << "Insufficient network mode for RPC: "
<< mNetOps->strOperatingMode (); << netOps_.strOperatingMode ();
return rpcError (rpcNO_NETWORK); return rpcError (rpcNO_NETWORK);
} }
@@ -150,7 +129,7 @@ Json::Value RPCHandler::doCommand (
} }
if ((handler->condition_ & RPC::NEEDS_CLOSED_LEDGER) && if ((handler->condition_ & RPC::NEEDS_CLOSED_LEDGER) &&
!mNetOps->getClosedLedger ()) !netOps_.getClosedLedger ())
{ {
return rpcError (rpcNO_CLOSED); return rpcError (rpcNO_CLOSED);
} }
@@ -159,7 +138,7 @@ Json::Value RPCHandler::doCommand (
{ {
LoadEvent::autoptr ev = getApp().getJobQueue().getLoadEventAP( LoadEvent::autoptr ev = getApp().getJobQueue().getLoadEventAP(
jtGENERIC, "cmd:" + strCommand); jtGENERIC, "cmd:" + strCommand);
RPC::Context context{params, loadType, *mNetOps, mInfoSub, mRole}; RPC::Context context {params, loadType, netOps_, infoSub_, role_};
Json::Value jvRaw = handler->method_(context); Json::Value jvRaw = handler->method_(context);
// Regularize result. // Regularize result.
@@ -183,36 +162,4 @@ Json::Value RPCHandler::doCommand (
} }
} }
RPCInternalHandler* RPCInternalHandler::sHeadHandler = nullptr;
RPCInternalHandler::RPCInternalHandler (
std::string const& name, handler_t Handler)
: mName (name),
mHandler (Handler)
{
mNextHandler = sHeadHandler;
sHeadHandler = this;
}
Json::Value RPCInternalHandler::runHandler (
std::string const& name, Json::Value const& params)
{
for (RPCInternalHandler* h = sHeadHandler; h != nullptr; )
{
if (name == h->mName)
{
WriteLog (lsWARNING, RPCHandler)
<< "Internal command " << name << ": " << params;
Json::Value ret = h->mHandler (params);
WriteLog (lsWARNING, RPCHandler)
<< "Internal command returns: " << ret;
return ret;
}
h = h->mNextHandler;
}
return rpcError (rpcBAD_SYNTAX);
}
} // ripple } // ripple

View File

@@ -20,10 +20,13 @@
#include <ripple/module/app/main/RPCHTTPServer.h> #include <ripple/module/app/main/RPCHTTPServer.h>
#include <ripple/module/rpc/RPCHandler.h> #include <ripple/module/rpc/RPCHandler.h>
#include <ripple/module/rpc/RPCServerHandler.h> #include <ripple/module/rpc/RPCServerHandler.h>
#include <ripple/module/rpc/Tuning.h>
namespace ripple { namespace ripple {
RPCServerHandler::RPCServerHandler (NetworkOPs& networkOPs, Resource::Manager& resourceManager) RPCServerHandler::RPCServerHandler (
NetworkOPs& networkOPs,
Resource::Manager& resourceManager)
: m_networkOPs (networkOPs) : m_networkOPs (networkOPs)
, m_resourceManager (resourceManager) , m_resourceManager (resourceManager)
{ {
@@ -42,14 +45,15 @@ bool RPCServerHandler::isAuthorized (
return HTTPAuthorized (headers); return HTTPAuthorized (headers);
} }
std::string RPCServerHandler::processRequest (std::string const& request, std::string RPCServerHandler::processRequest (
std::string const& request,
beast::IP::Endpoint const& remoteIPAddress) beast::IP::Endpoint const& remoteIPAddress)
{ {
Json::Value jsonRequest; Json::Value jsonRequest;
{ {
Json::Reader reader; Json::Reader reader;
if ((request.size() > 1000000) || if ((request.size() > RPC::MAX_REQUEST_SIZE) ||
! reader.parse (request, jsonRequest) || ! reader.parse (request, jsonRequest) ||
jsonRequest.isNull () || jsonRequest.isNull () ||
! jsonRequest.isObject ()) ! jsonRequest.isObject ())
@@ -58,14 +62,19 @@ std::string RPCServerHandler::processRequest (std::string const& request,
} }
} }
Config::Role const role (getConfig ().getAdminRole (jsonRequest, remoteIPAddress)); auto const role = getConfig ().getAdminRole (jsonRequest, remoteIPAddress);
Resource::Consumer usage; Resource::Consumer usage;
if (role == Config::ADMIN) if (role == Config::ADMIN)
usage = m_resourceManager.newAdminEndpoint (remoteIPAddress.to_string()); {
usage = m_resourceManager.newAdminEndpoint (
remoteIPAddress.to_string());
}
else else
{
usage = m_resourceManager.newInboundEndpoint (remoteIPAddress); usage = m_resourceManager.newInboundEndpoint (remoteIPAddress);
}
if (usage.disconnect ()) if (usage.disconnect ())
return createResponse (503, "Server is overloaded"); return createResponse (503, "Server is overloaded");
@@ -75,19 +84,17 @@ std::string RPCServerHandler::processRequest (std::string const& request,
// VFALCO NOTE Except that "id" isn't included in the following errors... // VFALCO NOTE Except that "id" isn't included in the following errors...
// //
Json::Value const& id = jsonRequest ["id"]; Json::Value const& id = jsonRequest ["id"];
Json::Value const& method = jsonRequest ["method"]; Json::Value const& method = jsonRequest ["method"];
if (method.isNull ()) if (method.isNull ())
{
return createResponse (400, "Null method"); return createResponse (400, "Null method");
}
else if (! method.isString ())
{
return createResponse (400, "method is not string");
}
std::string strMethod = method.asString (); if (! method.isString ())
return createResponse (400, "method is not string");
auto strMethod = method.asString ();
if (strMethod.empty())
return createResponse (400, "method is empty");
if (jsonRequest["params"].isNull()) if (jsonRequest["params"].isNull())
jsonRequest["params"] = Json::Value (Json::arrayValue); jsonRequest["params"] = Json::Value (Json::arrayValue);
@@ -149,7 +156,6 @@ std::string RPCServerHandler::processRequest (std::string const& request,
usage.charge (fee); usage.charge (fee);
WriteLog (lsDEBUG, RPCServer) << "Reply: " << result; WriteLog (lsDEBUG, RPCServer) << "Reply: " << result;
response = JSONRPCReply (result, Json::Value (), id); response = JSONRPCReply (result, Json::Value (), id);
return createResponse (200, response); return createResponse (200, response);

View File

@@ -47,8 +47,11 @@ namespace RPC {
@param result A JSON object for injecting error results, if any @param result A JSON object for injecting error results, if any
@param admin `true` if this is called by an administrative endpoint. @param admin `true` if this is called by an administrative endpoint.
*/ */
static void autofill_fee (Json::Value& request, static void autofill_fee (
Ledger::pointer ledger, Json::Value& result, bool admin) Json::Value& request,
Ledger::pointer ledger,
Json::Value& result,
bool admin)
{ {
Json::Value& tx (request["tx_json"]); Json::Value& tx (request["tx_json"]);
if (tx.isMember ("Fee")) if (tx.isMember ("Fee"))
@@ -88,7 +91,6 @@ static void autofill_fee (Json::Value& request,
tx ["Fee"] = static_cast<int>(fee); tx ["Fee"] = static_cast<int>(fee);
} }
static Json::Value signPayment( static Json::Value signPayment(
Json::Value const& params, Json::Value const& params,
Json::Value& tx_json, Json::Value& tx_json,
@@ -150,12 +152,20 @@ static Json::Value signPayment(
bool bValid; bool bValid;
auto cache = std::make_shared<RippleLineCache> (lSnapshot); auto cache = std::make_shared<RippleLineCache> (lSnapshot);
Pathfinder pf (cache, raSrcAddressID, dstAccountID, Pathfinder pf (
saSendMax.getCurrency (), saSendMax.getIssuer (), cache,
raSrcAddressID,
dstAccountID,
saSendMax.getCurrency (),
saSendMax.getIssuer (),
amount, bValid); amount, bValid);
STPath extraPath; STPath extraPath;
if (!bValid || !pf.findPaths (getConfig ().PATH_SEARCH_OLD, 4, spsPaths, extraPath)) if (!bValid ||
!pf.findPaths (getConfig ().PATH_SEARCH_OLD,
4,
spsPaths,
extraPath))
{ {
WriteLog (lsDEBUG, RPCHandler) WriteLog (lsDEBUG, RPCHandler)
<< "transactionSign: build_path: No paths found."; << "transactionSign: build_path: No paths found.";
@@ -179,7 +189,10 @@ static Json::Value signPayment(
// submit the tranaction // submit the tranaction
// //
Json::Value transactionSign ( Json::Value transactionSign (
Json::Value params, bool bSubmit, bool bFailHard, NetworkOPs& netOps, Json::Value params,
bool bSubmit,
bool bFailHard,
NetworkOPs& netOps,
int role) int role)
{ {
Json::Value jvResult; Json::Value jvResult;
@@ -242,7 +255,8 @@ Json::Value transactionSign (
{ {
// If not offline and did not find account, error. // If not offline and did not find account, error.
WriteLog (lsDEBUG, RPCHandler) WriteLog (lsDEBUG, RPCHandler)
<< "transactionSign: Failed to find source account in current ledger: " << "transactionSign: Failed to find source account "
<< "in current ledger: "
<< raSrcAddressID.humanAccountID (); << raSrcAddressID.humanAccountID ();
return rpcError (rpcSRC_ACT_NOT_FOUND); return rpcError (rpcSRC_ACT_NOT_FOUND);
@@ -255,7 +269,12 @@ Json::Value transactionSign (
if ("Payment" == sType) if ("Payment" == sType)
{ {
auto e = signPayment(params, tx_json, raSrcAddressID, lSnapshot, role); auto e = signPayment(
params,
tx_json,
raSrcAddressID,
lSnapshot,
role);
if (contains_error(e)) if (contains_error(e))
return e; return e;
} }
@@ -287,12 +306,12 @@ Json::Value transactionSign (
return rpcError (rpcSRC_ACT_NOT_FOUND); return rpcError (rpcSRC_ACT_NOT_FOUND);
} }
RippleAddress naSecret = RippleAddress::createSeedGeneric ( RippleAddress secret = RippleAddress::createSeedGeneric (
params["secret"].asString ()); params["secret"].asString ());
RippleAddress naMasterGenerator = RippleAddress::createGeneratorPublic ( RippleAddress masterGenerator = RippleAddress::createGeneratorPublic (
naSecret); secret);
RippleAddress masterAccountPublic = RippleAddress::createAccountPublic ( RippleAddress masterAccountPublic = RippleAddress::createAccountPublic (
naMasterGenerator, 0); masterGenerator, 0);
if (verify) if (verify)
{ {
@@ -323,7 +342,9 @@ Json::Value transactionSign (
return jvResult; return jvResult;
} }
std::unique_ptr<STObject> sopTrans = std::move(parsed.object); std::unique_ptr<STObject> sopTrans = std::move(parsed.object);
sopTrans->setFieldVL (sfSigningPubKey, masterAccountPublic.getAccountPublic ()); sopTrans->setFieldVL (
sfSigningPubKey,
masterAccountPublic.getAccountPublic ());
SerializedTransaction::pointer stpTrans; SerializedTransaction::pointer stpTrans;
@@ -348,9 +369,10 @@ Json::Value transactionSign (
jvResult["tx_signing_hash"] = to_string (stpTrans->getSigningHash ()); jvResult["tx_signing_hash"] = to_string (stpTrans->getSigningHash ());
} }
// FIXME: For performance, transactions should not be signed in this code path. // FIXME: For performance, transactions should not be signed in this code
// path.
RippleAddress naAccountPrivate = RippleAddress::createAccountPrivate ( RippleAddress naAccountPrivate = RippleAddress::createAccountPrivate (
naMasterGenerator, naSecret, 0); masterGenerator, secret, 0);
stpTrans->sign (naAccountPrivate); stpTrans->sign (naAccountPrivate);
@@ -416,9 +438,12 @@ class JSONRPC_test : public beast::unit_test::suite
public: public:
void testAutoFillFees () void testAutoFillFees ()
{ {
RippleAddress rootSeedMaster = RippleAddress::createSeedGeneric ("masterpassphrase"); RippleAddress rootSeedMaster
RippleAddress rootGeneratorMaster = RippleAddress::createGeneratorPublic (rootSeedMaster); = RippleAddress::createSeedGeneric ("masterpassphrase");
RippleAddress rootAddress = RippleAddress::createAccountPublic (rootGeneratorMaster, 0); RippleAddress rootGeneratorMaster
= RippleAddress::createGeneratorPublic (rootSeedMaster);
RippleAddress rootAddress
= RippleAddress::createAccountPublic (rootGeneratorMaster, 0);
std::uint64_t startAmount (100000); std::uint64_t startAmount (100000);
Ledger::pointer ledger (std::make_shared <Ledger> ( Ledger::pointer ledger (std::make_shared <Ledger> (
rootAddress, startAmount)); rootAddress, startAmount));

View File

@@ -53,6 +53,7 @@
#include <ripple/module/rpc/handlers/Feature.cpp> #include <ripple/module/rpc/handlers/Feature.cpp>
#include <ripple/module/rpc/handlers/FetchInfo.cpp> #include <ripple/module/rpc/handlers/FetchInfo.cpp>
#include <ripple/module/rpc/handlers/GetCounts.cpp> #include <ripple/module/rpc/handlers/GetCounts.cpp>
#include <ripple/module/rpc/handlers/Internal.cpp>
#include <ripple/module/rpc/handlers/Ledger.cpp> #include <ripple/module/rpc/handlers/Ledger.cpp>
#include <ripple/module/rpc/handlers/LedgerAccept.cpp> #include <ripple/module/rpc/handlers/LedgerAccept.cpp>
#include <ripple/module/rpc/handlers/LedgerCleaner.cpp> #include <ripple/module/rpc/handlers/LedgerCleaner.cpp>
@@ -69,7 +70,6 @@
#include <ripple/module/rpc/handlers/Peers.cpp> #include <ripple/module/rpc/handlers/Peers.cpp>
#include <ripple/module/rpc/handlers/Ping.cpp> #include <ripple/module/rpc/handlers/Ping.cpp>
#include <ripple/module/rpc/handlers/Print.cpp> #include <ripple/module/rpc/handlers/Print.cpp>
#include <ripple/module/rpc/handlers/Profile.cpp>
#include <ripple/module/rpc/handlers/ProofCreate.cpp> #include <ripple/module/rpc/handlers/ProofCreate.cpp>
#include <ripple/module/rpc/handlers/ProofSolve.cpp> #include <ripple/module/rpc/handlers/ProofSolve.cpp>
#include <ripple/module/rpc/handlers/ProofVerify.cpp> #include <ripple/module/rpc/handlers/ProofVerify.cpp>