Reorganize source file hierarchy:

* Rename unity files
* Move some modules to new subdirectories
* Remove obsolete Visual Studio project files
* Remove obsolete coding style and TODO list
This commit is contained in:
Vinnie Falco
2014-06-03 14:48:34 -07:00
parent 39a387b54c
commit 4f1d1d2a8a
774 changed files with 6924 additions and 10355 deletions

View File

@@ -0,0 +1,3 @@
# RPC
New code to generalize the operation of RPC commands

View File

@@ -0,0 +1,6 @@
# RPC TODO
- Redo the interface to actually work correctly for the existing
use-cases that the old code supports. Specifically that RPC commands
can be issued for a particular context like a websocket connection
or other subscriber.

View File

@@ -0,0 +1,212 @@
//------------------------------------------------------------------------------
/*
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_RPC_ERRORCODES_H_INCLUDED
#define RIPPLE_RPC_ERRORCODES_H_INCLUDED
#include <ripple/unity/json.h>
namespace ripple {
// VFALCO NOTE These are outside the RPC namespace
enum error_code_i
{
rpcUNKNOWN = -1, // Represents codes not listed in this enumeration
rpcSUCCESS = 0,
rpcBAD_SYNTAX, // Must be 1 to print usage to command line.
rpcJSON_RPC,
rpcFORBIDDEN,
// Error numbers beyond this line are not stable between versions.
// Programs should use error tokens.
// Misc failure
rpcLOAD_FAILED,
rpcNO_PERMISSION,
rpcNO_EVENTS,
rpcNOT_STANDALONE,
rpcTOO_BUSY,
rpcSLOW_DOWN,
rpcHIGH_FEE,
// Networking
rpcNO_CLOSED,
rpcNO_CURRENT,
rpcNO_NETWORK,
// Ledger state
rpcACT_EXISTS,
rpcACT_NOT_FOUND,
rpcINSUF_FUNDS,
rpcLGR_NOT_FOUND,
rpcMASTER_DISABLED,
rpcNICKNAME_MISSING,
rpcNO_ACCOUNT,
rpcNO_PATH,
rpcPASSWD_CHANGED,
rpcSRC_MISSING,
rpcSRC_UNCLAIMED,
rpcTXN_NOT_FOUND,
rpcWRONG_SEED,
// Malformed command
rpcINVALID_PARAMS,
rpcUNKNOWN_COMMAND,
rpcNO_PF_REQUEST,
// Bad parameter
rpcACT_BITCOIN,
rpcACT_MALFORMED,
rpcQUALITY_MALFORMED,
rpcBAD_BLOB,
rpcBAD_FEATURE,
rpcBAD_ISSUER,
rpcBAD_MARKET,
rpcBAD_SECRET,
rpcBAD_SEED,
rpcCOMMAND_MISSING,
rpcDST_ACT_MALFORMED,
rpcDST_ACT_MISSING,
rpcDST_AMT_MALFORMED,
rpcDST_ISR_MALFORMED,
rpcGETS_ACT_MALFORMED,
rpcGETS_AMT_MALFORMED,
rpcHOST_IP_MALFORMED,
rpcLGR_IDXS_INVALID,
rpcLGR_IDX_MALFORMED,
rpcNICKNAME_MALFORMED,
rpcNICKNAME_PERM,
rpcPAYS_ACT_MALFORMED,
rpcPAYS_AMT_MALFORMED,
rpcPORT_MALFORMED,
rpcPUBLIC_MALFORMED,
rpcSRC_ACT_MALFORMED,
rpcSRC_ACT_MISSING,
rpcSRC_ACT_NOT_FOUND,
rpcSRC_AMT_MALFORMED,
rpcSRC_CUR_MALFORMED,
rpcSRC_ISR_MALFORMED,
rpcATX_DEPRECATED,
// Internal error (should never happen)
rpcINTERNAL, // Generic internal error.
rpcFAIL_GEN_DECRYPT,
rpcNOT_IMPL,
rpcNOT_SUPPORTED,
rpcNO_GEN_DECRYPT,
};
//------------------------------------------------------------------------------
namespace RPC {
/** Maps an rpc error code to its token and default message. */
struct ErrorInfo
{
ErrorInfo (error_code_i code_, std::string const& token_,
std::string const& message_)
: code (code_)
, token (token_)
, message (message_)
{ }
error_code_i code;
std::string token;
std::string message;
};
/** Returns an ErrorInfo that reflects the error code. */
ErrorInfo const& get_error_info (error_code_i code);
/** Add or update the json update to reflect the error code. */
/** @{ */
void inject_error (error_code_i code, Json::Value& json);
inline void inject_error (int code, Json::Value& json)
{ inject_error (error_code_i (code), json); }
void inject_error (error_code_i code, std::string const& message, Json::Value& json);
/** @} */
/** Returns a new json object that reflects the error code. */
/** @{ */
Json::Value make_error (error_code_i code);
Json::Value make_error (error_code_i code, std::string const& message);
/** @} */
/** Returns a new json object that indicates invalid parameters. */
/** @{ */
inline Json::Value make_param_error (std::string const& message)
{
return make_error (rpcINVALID_PARAMS, message);
}
inline std::string missing_field_message (std::string const& name)
{
return "Missing field '" + name + "'.";
}
inline Json::Value missing_field_error (std::string const& name)
{
return make_param_error (missing_field_message (name));
}
inline std::string object_field_message (std::string const& name)
{
return "Invalid field '" + name + "', not object.";
}
inline Json::Value object_field_error (std::string const& name)
{
return make_param_error (object_field_message (name));
}
inline std::string invalid_field_message (std::string const& name)
{
return "Invalid field '" + name + "'.";
}
inline Json::Value invalid_field_error (std::string const& name)
{
return make_param_error (object_field_message (name));
}
inline std::string expected_field_message (
std::string const& name, std::string const& type)
{
return "Invalid field '" + name + "', not " + type + ".";
}
inline Json::Value expected_field_error (
std::string const& name, std::string const& type)
{
return make_param_error (expected_field_message (name, type));
}
/** @} */
/** Returns `true` if the json contains an rpc error specification. */
bool contains_error (Json::Value const& json);
}
}
#endif

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
/*
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_RPC_MANAGER_H_INCLUDED
#define RIPPLE_RPC_MANAGER_H_INCLUDED
#include <ripple/module/rpc/api/Request.h>
namespace ripple {
namespace RPC {
/** Processes RPC commands. */
class Manager
{
public:
typedef std::function <void (Request&)> handler_type;
virtual ~Manager () = 0;
/** Add a handler for the specified JSON-RPC command. */
/** @{ */
template <class Handler>
void add (std::string const& method)
{
add (method, handler_type (
[](Request& req)
{
Handler h;
h (req);
}));
}
virtual void add (std::string const& method, handler_type&& handler) = 0;
/** @} */
/** Dispatch the JSON-RPC request.
@return `true` If the command was found.
*/
virtual bool dispatch (Request& req) = 0;
};
std::unique_ptr <Manager> make_Manager (beast::Journal journal);
}
}
#endif

View File

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
/*
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_RPC_REQUEST_H_INCLUDED
#define RIPPLE_RPC_REQUEST_H_INCLUDED
#include <ripple/unity/json.h>
#include <ripple/unity/resource.h>
namespace ripple {
class Application; // forward declare
namespace RPC {
struct Request
{
explicit Request (beast::Journal journal_,
std::string const& method_, Json::Value& params_,
Application& app_)
: journal (journal_)
, method (method_)
, params (params_)
, fee (Resource::feeReferenceRPC)
, app (app_)
{
}
// [in] The Journal for logging
beast::Journal journal;
// [in] The JSON-RPC method
std::string method;
// [in] The Ripple-specific "params" object
Json::Value params;
// [in, out] The resource cost for the command
Resource::Charge fee;
// [out] The JSON-RPC response
Json::Value result;
// [in] The Application instance
Application& app;
private:
Request& operator= (Request const&);
};
}
}
#endif

View File

@@ -0,0 +1,35 @@
//------------------------------------------------------------------------------
/*
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_RPC_TUNING_H
#define RIPPLE_RPC_TUNING_H
namespace ripple {
namespace RPC {
const int DEFAULT_AUTO_FILL_FEE_MULTIPLIER = 10;
const int MAX_PATHFINDS_IN_PROGRESS = 2;
const int MAX_PATHFIND_JOB_COUNT = 50;
// TODO(tom): Shouldn't DEFAULT_AUTO_FILL_FEE_MULTIPLIER be floating point?
} // RPC
} // ripple
#endif

View File

@@ -0,0 +1,85 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doAccountCurrencies (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
// Get the current ledger
Ledger::pointer lpLedger;
Json::Value jvResult (RPC::lookupLedger (params, lpLedger, *mNetOps));
if (!lpLedger)
return jvResult;
if (! params.isMember ("account") && ! params.isMember ("ident"))
return RPC::missing_field_error ("account");
std::string const strIdent (params.isMember ("account")
? params["account"].asString ()
: params["ident"].asString ());
int const iIndex (params.isMember ("account_index")
? params["account_index"].asUInt ()
: 0);
bool const bStrict (params.isMember ("strict") && params["strict"].asBool ());
// Get info on account.
bool bIndex; // out param
RippleAddress naAccount; // out param
Json::Value jvAccepted (RPC::accountFromString (
lpLedger, naAccount, bIndex, strIdent, iIndex, bStrict, *mNetOps));
if (!jvAccepted.empty ())
return jvAccepted;
std::set<uint160> send, receive;
AccountItems rippleLines (naAccount.getAccountID (), lpLedger, AccountItem::pointer (new RippleState ()));
BOOST_FOREACH(AccountItem::ref item, rippleLines.getItems ())
{
RippleState* rspEntry = (RippleState*) item.get ();
const STAmount& saBalance = rspEntry->getBalance ();
if (saBalance < rspEntry->getLimit ())
receive.insert (saBalance.getCurrency ());
if ((-saBalance) < rspEntry->getLimitPeer ())
send.insert (saBalance.getCurrency ());
}
send.erase (CURRENCY_BAD);
receive.erase (CURRENCY_BAD);
Json::Value& sendCurrencies = (jvResult["send_currencies"] = Json::arrayValue);
BOOST_FOREACH(uint160 const& c, send)
{
sendCurrencies.append (STAmount::createHumanCurrency (c));
}
Json::Value& recvCurrencies = (jvResult["receive_currencies"] = Json::arrayValue);
BOOST_FOREACH(uint160 const& c, receive)
{
recvCurrencies.append (STAmount::createHumanCurrency (c));
}
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,72 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// account: <indent>,
// account_index : <index> // optional
// strict: <bool> // true, only allow public keys and addresses. false, default.
// ledger_hash : <ledger>
// ledger_index : <ledger_index>
// }
Json::Value RPCHandler::doAccountInfo (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
Ledger::pointer lpLedger;
Json::Value jvResult = RPC::lookupLedger (params, lpLedger, *mNetOps);
if (!lpLedger)
return jvResult;
if (!params.isMember ("account") && !params.isMember ("ident"))
return RPC::missing_field_error ("account");
std::string strIdent = params.isMember ("account") ? params["account"].asString () : params["ident"].asString ();
bool bIndex;
int iIndex = params.isMember ("account_index") ? params["account_index"].asUInt () : 0;
bool bStrict = params.isMember ("strict") && params["strict"].asBool ();
RippleAddress naAccount;
// Get info on account.
Json::Value jvAccepted = RPC::accountFromString (lpLedger, naAccount, bIndex, strIdent, iIndex, bStrict, *mNetOps);
if (!jvAccepted.empty ())
return jvAccepted;
AccountState::pointer asAccepted = mNetOps->getAccountState (lpLedger, naAccount);
if (asAccepted)
{
asAccepted->addJson (jvAccepted);
jvResult["account_data"] = jvAccepted;
}
else
{
jvResult["account"] = naAccount.humanAccountID ();
jvResult = rpcError (rpcACT_NOT_FOUND, jvResult);
}
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,122 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// account: <account>|<nickname>|<account_public_key>
// account_index: <number> // optional, defaults to 0.
// ledger_hash : <ledger>
// ledger_index : <ledger_index>
// }
Json::Value RPCHandler::doAccountLines (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
Ledger::pointer lpLedger;
Json::Value jvResult = RPC::lookupLedger (params, lpLedger, *mNetOps);
if (!lpLedger)
return jvResult;
if (!params.isMember (jss::account))
return RPC::missing_field_error ("account");
std::string strIdent = params[jss::account].asString ();
bool bIndex = params.isMember (jss::account_index);
int iIndex = bIndex ? params[jss::account_index].asUInt () : 0;
RippleAddress raAccount;
jvResult = RPC::accountFromString (lpLedger, raAccount, bIndex, strIdent, iIndex, false, *mNetOps);
if (!jvResult.empty ())
return jvResult;
std::string strPeer = params.isMember (jss::peer) ? params[jss::peer].asString () : "";
bool bPeerIndex = params.isMember (jss::peer_index);
int iPeerIndex = bIndex ? params[jss::peer_index].asUInt () : 0;
RippleAddress raPeer;
if (!strPeer.empty ())
{
jvResult[jss::peer] = raAccount.humanAccountID ();
if (bPeerIndex)
jvResult[jss::peer_index] = iPeerIndex;
jvResult = RPC::accountFromString (lpLedger, raPeer, bPeerIndex, strPeer, iPeerIndex, false, *mNetOps);
if (!jvResult.empty ())
return jvResult;
}
if (lpLedger->hasAccount (raAccount))
{
AccountItems rippleLines (raAccount.getAccountID (), lpLedger, AccountItem::pointer (new RippleState ()));
jvResult[jss::account] = raAccount.humanAccountID ();
Json::Value& jsonLines = (jvResult[jss::lines] = Json::arrayValue);
BOOST_FOREACH (AccountItem::ref item, rippleLines.getItems ())
{
RippleState* line = (RippleState*)item.get ();
if (!raPeer.isValid () || raPeer.getAccountID () == line->getAccountIDPeer ())
{
const STAmount& saBalance = line->getBalance ();
const STAmount& saLimit = line->getLimit ();
const STAmount& saLimitPeer = line->getLimitPeer ();
Json::Value& jPeer = jsonLines.append (Json::objectValue);
jPeer[jss::account] = RippleAddress::createHumanAccountID (line->getAccountIDPeer ());
// Amount reported is positive if current account holds other account's IOUs.
// Amount reported is negative if other account holds current account's IOUs.
jPeer[jss::balance] = saBalance.getText ();
jPeer[jss::currency] = saBalance.getHumanCurrency ();
jPeer[jss::limit] = saLimit.getText ();
jPeer[jss::limit_peer] = saLimitPeer.getText ();
jPeer[jss::quality_in] = static_cast<Json::UInt> (line->getQualityIn ());
jPeer[jss::quality_out] = static_cast<Json::UInt> (line->getQualityOut ());
if (line->getAuth())
jPeer[jss::authorized] = true;
if (line->getAuthPeer())
jPeer[jss::peer_authorized] = true;
if (line->getNoRipple())
jPeer[jss::no_ripple] = true;
if (line->getNoRipplePeer())
jPeer[jss::no_ripple_peer] = true;
}
}
loadType = Resource::feeMediumBurdenRPC;
}
else
{
jvResult = rpcError (rpcACT_NOT_FOUND);
}
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,85 @@
//------------------------------------------------------------------------------
/*
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 {
static void offerAdder (Json::Value& jvLines, SLE::ref offer)
{
if (offer->getType () == ltOFFER)
{
Json::Value& obj = jvLines.append (Json::objectValue);
offer->getFieldAmount (sfTakerPays).setJson (obj[jss::taker_pays]);
offer->getFieldAmount (sfTakerGets).setJson (obj[jss::taker_gets]);
obj[jss::seq] = offer->getFieldU32 (sfSequence);
obj[jss::flags] = offer->getFieldU32 (sfFlags);
}
}
// {
// account: <account>|<nickname>|<account_public_key>
// account_index: <number> // optional, defaults to 0.
// ledger_hash : <ledger>
// ledger_index : <ledger_index>
// }
Json::Value RPCHandler::doAccountOffers (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
Ledger::pointer lpLedger;
Json::Value jvResult = RPC::lookupLedger (params, lpLedger, *mNetOps);
if (!lpLedger)
return jvResult;
if (!params.isMember (jss::account))
return RPC::missing_field_error ("account");
std::string strIdent = params[jss::account].asString ();
bool bIndex = params.isMember (jss::account_index);
int iIndex = bIndex ? params[jss::account_index].asUInt () : 0;
RippleAddress raAccount;
jvResult = RPC::accountFromString (lpLedger, raAccount, bIndex, strIdent, iIndex, false, *mNetOps);
if (!jvResult.empty ())
return jvResult;
// Get info on account.
jvResult[jss::account] = raAccount.humanAccountID ();
if (bIndex)
jvResult[jss::account_index] = iIndex;
if (!lpLedger->hasAccount (raAccount))
return rpcError (rpcACT_NOT_FOUND);
Json::Value& jvsOffers = (jvResult[jss::offers] = Json::arrayValue);
lpLedger->visitAccountItems (raAccount.getAccountID (),
std::bind (&offerAdder, boost::ref (jvsOffers),
std::placeholders::_1));
loadType = Resource::feeMediumBurdenRPC;
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,162 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// account: account,
// ledger_index_min: ledger_index // optional, defaults to earliest
// ledger_index_max: ledger_index, // optional, defaults to latest
// binary: boolean, // optional, defaults to false
// forward: boolean, // optional, defaults to false
// limit: integer, // optional
// marker: opaque // optional, resume previous query
// }
Json::Value RPCHandler::doAccountTx (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
RippleAddress raAccount;
int limit = params.isMember (jss::limit) ? params[jss::limit].asUInt () : -1;
bool bBinary = params.isMember ("binary") && params["binary"].asBool ();
bool bForward = params.isMember ("forward") && params["forward"].asBool ();
std::uint32_t uLedgerMin;
std::uint32_t uLedgerMax;
std::uint32_t uValidatedMin;
std::uint32_t uValidatedMax;
bool bValidated = mNetOps->getValidatedRange (uValidatedMin, uValidatedMax);
if (!bValidated)
{
// Don't have a validated ledger range.
return rpcError (rpcLGR_IDXS_INVALID);
}
if (!params.isMember ("account"))
return rpcError (rpcINVALID_PARAMS);
if (!raAccount.setAccountID (params["account"].asString ()))
return rpcError (rpcACT_MALFORMED);
loadType = Resource::feeMediumBurdenRPC;
if (params.isMember ("ledger_index_min") || params.isMember ("ledger_index_max"))
{
std::int64_t iLedgerMin = params.isMember ("ledger_index_min") ? params["ledger_index_min"].asInt () : -1;
std::int64_t iLedgerMax = params.isMember ("ledger_index_max") ? params["ledger_index_max"].asInt () : -1;
uLedgerMin = iLedgerMin == -1 ? uValidatedMin : iLedgerMin;
uLedgerMax = iLedgerMax == -1 ? uValidatedMax : iLedgerMax;
if (uLedgerMax < uLedgerMin)
{
return rpcError (rpcLGR_IDXS_INVALID);
}
}
else
{
Ledger::pointer l;
Json::Value ret = RPC::lookupLedger (params, l, *mNetOps);
if (!l)
return ret;
uLedgerMin = uLedgerMax = l->getLedgerSeq ();
}
Json::Value resumeToken;
if (params.isMember(jss::marker))
{
resumeToken = params[jss::marker];
}
#ifndef BEAST_DEBUG
try
{
#endif
Json::Value ret (Json::objectValue);
ret["account"] = raAccount.humanAccountID ();
Json::Value& jvTxns = (ret["transactions"] = Json::arrayValue);
if (bBinary)
{
std::vector<NetworkOPs::txnMetaLedgerType> txns =
mNetOps->getTxsAccountB (raAccount, uLedgerMin, uLedgerMax, bForward, resumeToken, limit, mRole == Config::ADMIN);
for (std::vector<NetworkOPs::txnMetaLedgerType>::const_iterator it = txns.begin (), end = txns.end ();
it != end; ++it)
{
Json::Value& jvObj = jvTxns.append (Json::objectValue);
std::uint32_t uLedgerIndex = std::get<2> (*it);
jvObj["tx_blob"] = std::get<0> (*it);
jvObj["meta"] = std::get<1> (*it);
jvObj["ledger_index"] = uLedgerIndex;
jvObj[jss::validated] = bValidated && uValidatedMin <= uLedgerIndex && uValidatedMax >= uLedgerIndex;
}
}
else
{
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> > txns =
mNetOps->getTxsAccount (raAccount, uLedgerMin, uLedgerMax, bForward, resumeToken, limit, mRole == Config::ADMIN);
for (std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >::iterator it = txns.begin (), end = txns.end (); it != end; ++it)
{
Json::Value& jvObj = jvTxns.append (Json::objectValue);
if (it->first)
jvObj[jss::tx] = it->first->getJson (1);
if (it->second)
{
std::uint32_t uLedgerIndex = it->second->getLgrSeq ();
jvObj[jss::meta] = it->second->getJson (0);
jvObj[jss::validated] = bValidated && uValidatedMin <= uLedgerIndex && uValidatedMax >= uLedgerIndex;
}
}
}
//Add information about the original query
ret[jss::ledger_index_min] = uLedgerMin;
ret[jss::ledger_index_max] = uLedgerMax;
if (params.isMember (jss::limit))
ret[jss::limit] = limit;
if (!resumeToken.isNull())
ret[jss::marker] = resumeToken;
return ret;
#ifndef BEAST_DEBUG
}
catch (...)
{
return rpcError (rpcINTERNAL);
}
#endif
}
} // ripple

View File

@@ -0,0 +1,185 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// account: account,
// ledger_index_min: ledger_index,
// ledger_index_max: ledger_index,
// binary: boolean, // optional, defaults to false
// count: boolean, // optional, defaults to false
// descending: boolean, // optional, defaults to false
// offset: integer, // optional, defaults to 0
// limit: integer // optional
// }
Json::Value RPCHandler::doAccountTxOld (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
RippleAddress raAccount;
std::uint32_t offset = params.isMember ("offset") ? params["offset"].asUInt () : 0;
int limit = params.isMember ("limit") ? params["limit"].asUInt () : -1;
bool bBinary = params.isMember ("binary") && params["binary"].asBool ();
bool bDescending = params.isMember ("descending") && params["descending"].asBool ();
bool bCount = params.isMember ("count") && params["count"].asBool ();
std::uint32_t uLedgerMin;
std::uint32_t uLedgerMax;
std::uint32_t uValidatedMin;
std::uint32_t uValidatedMax;
bool bValidated = mNetOps->getValidatedRange (uValidatedMin, uValidatedMax);
if (!params.isMember ("account"))
return rpcError (rpcINVALID_PARAMS);
if (!raAccount.setAccountID (params["account"].asString ()))
return rpcError (rpcACT_MALFORMED);
if (offset > 3000)
return rpcError (rpcATX_DEPRECATED);
loadType = Resource::feeHighBurdenRPC;
// DEPRECATED
if (params.isMember ("ledger_min"))
{
params["ledger_index_min"] = params["ledger_min"];
bDescending = true;
}
// DEPRECATED
if (params.isMember ("ledger_max"))
{
params["ledger_index_max"] = params["ledger_max"];
bDescending = true;
}
if (params.isMember ("ledger_index_min") || params.isMember ("ledger_index_max"))
{
std::int64_t iLedgerMin = params.isMember ("ledger_index_min") ? params["ledger_index_min"].asInt () : -1;
std::int64_t iLedgerMax = params.isMember ("ledger_index_max") ? params["ledger_index_max"].asInt () : -1;
if (!bValidated && (iLedgerMin == -1 || iLedgerMax == -1))
{
// Don't have a validated ledger range.
return rpcError (rpcLGR_IDXS_INVALID);
}
uLedgerMin = iLedgerMin == -1 ? uValidatedMin : iLedgerMin;
uLedgerMax = iLedgerMax == -1 ? uValidatedMax : iLedgerMax;
if (uLedgerMax < uLedgerMin)
{
return rpcError (rpcLGR_IDXS_INVALID);
}
}
else
{
Ledger::pointer l;
Json::Value ret = RPC::lookupLedger (params, l, *mNetOps);
if (!l)
return ret;
uLedgerMin = uLedgerMax = l->getLedgerSeq ();
}
int count = 0;
#ifndef BEAST_DEBUG
try
{
#endif
Json::Value ret (Json::objectValue);
ret["account"] = raAccount.humanAccountID ();
Json::Value& jvTxns = (ret["transactions"] = Json::arrayValue);
if (bBinary)
{
std::vector<NetworkOPs::txnMetaLedgerType> txns =
mNetOps->getAccountTxsB (raAccount, uLedgerMin, uLedgerMax, bDescending, offset, limit, mRole == Config::ADMIN);
for (std::vector<NetworkOPs::txnMetaLedgerType>::const_iterator it = txns.begin (), end = txns.end ();
it != end; ++it)
{
++count;
Json::Value& jvObj = jvTxns.append (Json::objectValue);
std::uint32_t uLedgerIndex = std::get<2> (*it);
jvObj["tx_blob"] = std::get<0> (*it);
jvObj["meta"] = std::get<1> (*it);
jvObj["ledger_index"] = uLedgerIndex;
jvObj["validated"] = bValidated && uValidatedMin <= uLedgerIndex && uValidatedMax >= uLedgerIndex;
}
}
else
{
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> > txns = mNetOps->getAccountTxs (raAccount, uLedgerMin, uLedgerMax, bDescending, offset, limit, mRole == Config::ADMIN);
for (std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >::iterator it = txns.begin (), end = txns.end (); it != end; ++it)
{
++count;
Json::Value& jvObj = jvTxns.append (Json::objectValue);
if (it->first)
jvObj["tx"] = it->first->getJson (1);
if (it->second)
{
std::uint32_t uLedgerIndex = it->second->getLgrSeq ();
jvObj["meta"] = it->second->getJson (0);
jvObj["validated"] = bValidated && uValidatedMin <= uLedgerIndex && uValidatedMax >= uLedgerIndex;
}
}
}
//Add information about the original query
ret["ledger_index_min"] = uLedgerMin;
ret["ledger_index_max"] = uLedgerMax;
ret["validated"] = bValidated && uValidatedMin <= uLedgerMin && uValidatedMax >= uLedgerMax;
ret["offset"] = offset;
// We no longer return the full count but only the count of returned transactions
// Computing this count was two expensive and this API is deprecated anyway
if (bCount)
ret["count"] = count;
if (params.isMember ("limit"))
ret["limit"] = limit;
return ret;
#ifndef BEAST_DEBUG
}
catch (...)
{
return rpcError (rpcINTERNAL);
}
#endif
}
} // ripple

View File

@@ -0,0 +1,31 @@
//------------------------------------------------------------------------------
/*
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 {
// Temporary switching code until the old account_tx is removed
Json::Value RPCHandler::doAccountTxSwitch (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
if (params.isMember("offset") || params.isMember("count") || params.isMember("descending") ||
params.isMember("ledger_max") || params.isMember("ledger_min"))
return doAccountTxOld(params, loadType, masterLockHolder);
return doAccountTx(params, loadType, masterLockHolder);
}
} // ripple

View File

@@ -0,0 +1,32 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doBlackList (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock();
if (params.isMember("threshold"))
return getApp().getResourceManager().getJson(params["threshold"].asInt());
else
return getApp().getResourceManager().getJson();
}
} // ripple

View File

@@ -0,0 +1,216 @@
//------------------------------------------------------------------------------
/*
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 {
template <class UnsignedInteger>
inline bool is_xrp (UnsignedInteger const& value)
{
return value.isZero();
}
template <class UnsignedInteger>
inline bool is_not_xrp (UnsignedInteger const& value)
{
return ! is_xrp (value);
}
inline uint160 const& xrp_issuer ()
{
return ACCOUNT_XRP;
}
inline uint160 const& xrp_currency ()
{
return CURRENCY_XRP;
}
inline uint160 const& neutral_issuer ()
{
return ACCOUNT_ONE;
}
Json::Value RPCHandler::doBookOffers (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
// VFALCO TODO Here is a terrible place for this kind of business
// logic. It needs to be moved elsewhere and documented,
// and encapsulated into a function.
if (getApp().getJobQueue ().getJobCountGE (jtCLIENT) > 200)
return rpcError (rpcTOO_BUSY);
Ledger::pointer lpLedger;
Json::Value jvResult (RPC::lookupLedger (params, lpLedger, *mNetOps));
if (!lpLedger)
return jvResult;
if (!params.isMember ("taker_pays"))
return RPC::missing_field_error ("taker_pays");
if (!params.isMember ("taker_gets"))
return RPC::missing_field_error ("taker_gets");
if (!params["taker_pays"].isObject ())
return RPC::object_field_error ("taker_pays");
if (!params["taker_gets"].isObject ())
return RPC::object_field_error ("taker_gets");
Json::Value const& taker_pays (params["taker_pays"]);
if (!taker_pays.isMember ("currency"))
return RPC::missing_field_error ("taker_pays.currency");
if (! taker_pays ["currency"].isString ())
return RPC::expected_field_error ("taker_pays.currency", "string");
Json::Value const& taker_gets = params["taker_gets"];
if (! taker_gets.isMember ("currency"))
return RPC::missing_field_error ("taker_gets.currency");
if (! taker_gets ["currency"].isString ())
return RPC::expected_field_error ("taker_gets.currency", "string");
uint160 pay_currency;
if (! STAmount::currencyFromString (
pay_currency, taker_pays ["currency"].asString ()))
{
WriteLog (lsINFO, RPCHandler) << "Bad taker_pays currency.";
return RPC::make_error (rpcSRC_CUR_MALFORMED,
"Invalid field 'taker_pays.currency', bad currency.");
}
uint160 get_currency;
if (! STAmount::currencyFromString (
get_currency, taker_gets ["currency"].asString ()))
{
WriteLog (lsINFO, RPCHandler) << "Bad taker_gets currency.";
return RPC::make_error (rpcDST_AMT_MALFORMED,
"Invalid field 'taker_gets.currency', bad currency.");
}
uint160 pay_issuer;
if (taker_pays.isMember ("issuer"))
{
if (! taker_pays ["issuer"].isString())
return RPC::expected_field_error ("taker_pays.issuer", "string");
if (! STAmount::issuerFromString (
pay_issuer, taker_pays ["issuer"].asString ()))
return RPC::make_error (rpcSRC_ISR_MALFORMED,
"Invalid field 'taker_pays.issuer', bad issuer.");
if (pay_issuer == neutral_issuer ())
return RPC::make_error (rpcSRC_ISR_MALFORMED,
"Invalid field 'taker_pays.issuer', bad issuer account one.");
}
else
{
pay_issuer = xrp_issuer ();
}
if (is_xrp (pay_currency) && ! is_xrp (pay_issuer))
return RPC::make_error (rpcSRC_ISR_MALFORMED,
"Unneeded field 'taker_pays.issuer' for XRP currency specification.");
if (is_not_xrp (pay_currency) && is_xrp (pay_issuer))
return RPC::make_error (rpcSRC_ISR_MALFORMED,
"Invalid field 'taker_pays.issuer', expected non-XRP issuer.");
uint160 get_issuer;
if (taker_gets.isMember ("issuer"))
{
if (! taker_gets ["issuer"].isString())
return RPC::expected_field_error ("taker_gets.issuer", "string");
if (! STAmount::issuerFromString (
get_issuer, taker_gets ["issuer"].asString ()))
return RPC::make_error (rpcDST_ISR_MALFORMED,
"Invalid field 'taker_gets.issuer', bad issuer.");
if (get_issuer == neutral_issuer ())
return RPC::make_error (rpcDST_ISR_MALFORMED,
"Invalid field 'taker_gets.issuer', bad issuer account one.");
}
else
{
get_issuer = xrp_issuer ();
}
if (is_xrp (get_currency) && ! is_xrp (get_issuer))
return RPC::make_error (rpcDST_ISR_MALFORMED,
"Unneeded field 'taker_gets.issuer' for XRP currency specification.");
if (is_not_xrp (get_currency) && is_xrp (get_issuer))
return RPC::make_error (rpcDST_ISR_MALFORMED,
"Invalid field 'taker_gets.issuer', expected non-XRP issuer.");
RippleAddress raTakerID;
if (params.isMember ("taker"))
{
if (! params ["taker"].isString ())
return RPC::expected_field_error ("taker", "string");
if (! raTakerID.setAccountID (params ["taker"].asString ()))
return RPC::invalid_field_error ("taker");
}
else
{
raTakerID.setAccountID (ACCOUNT_ONE);
}
if (pay_currency == get_currency && pay_issuer == get_issuer)
{
WriteLog (lsINFO, RPCHandler) << "taker_gets same as taker_pays.";
return RPC::make_error (rpcBAD_MARKET);
}
if (params.isMember ("limit") && ! params ["limit"].isIntegral())
return RPC::expected_field_error (
"limit", "integer");
unsigned int const iLimit (params.isMember ("limit")
? params ["limit"].asUInt ()
: 0);
bool const bProof (params.isMember ("proof"));
Json::Value const jvMarker (params.isMember ("marker")
? params["marker"]
: Json::Value (Json::nullValue));
mNetOps->getBookPage (lpLedger, pay_currency, pay_issuer,
get_currency, get_issuer, raTakerID.getAccountID (),
bProof, iLimit, jvMarker, jvResult);
loadType = Resource::feeMediumBurdenRPC;
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,57 @@
//------------------------------------------------------------------------------
/*
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/overlay/api/Overlay.h>
namespace ripple {
// {
// ip: <string>,
// port: <number>
// }
// XXX Might allow domain for manual connections.
Json::Value RPCHandler::doConnect (Json::Value params,
Resource::Charge& loadType,
Application::ScopedLockType& masterLockHolder)
{
if (getConfig ().RUN_STANDALONE)
return "cannot connect in standalone mode";
if (!params.isMember ("ip"))
return RPC::missing_field_error ("ip");
if (params.isMember ("port") && !params["port"].isConvertibleTo (Json::intValue))
return rpcError (rpcINVALID_PARAMS);
int iPort;
if(params.isMember ("port"))
iPort = params["port"].asInt ();
else
iPort = SYSTEM_PEER_PORT;
beast::IP::Endpoint ip (beast::IP::Endpoint::from_string(params["ip"].asString ()));
if (! is_unspecified (ip))
getApp().overlay ().connect (ip.at_port(iPort));
return "connecting";
}
} // ripple

View File

@@ -0,0 +1,31 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doConsensusInfo (Json::Value, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
Json::Value ret (Json::objectValue);
ret["info"] = mNetOps->getConsensusInfo ();
return ret;
}
} // ripple

View File

@@ -0,0 +1,70 @@
//------------------------------------------------------------------------------
/*
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 {
static void textTime (std::string& text, int& seconds, const char* unitName, int unitVal)
{
int i = seconds / unitVal;
if (i == 0)
return;
seconds -= unitVal * i;
if (!text.empty ())
text += ", ";
text += beast::lexicalCastThrow <std::string> (i);
text += " ";
text += unitName;
if (i > 1)
text += "s";
}
Json::Value RPCHandler::doFeature (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& mlh)
{
if (!params.isMember ("feature"))
{
Json::Value jvReply = Json::objectValue;
jvReply["features"] = getApp().getAmendmentTable ().getJson(0);
return jvReply;
}
uint256 uFeature = getApp().getAmendmentTable ().get(params["feature"].asString());
if (uFeature.isZero ())
{
uFeature.SetHex (params["feature"].asString ());
if (uFeature.isZero ())
return rpcError (rpcBAD_FEATURE);
}
if (!params.isMember ("vote"))
return getApp().getAmendmentTable ().getJson(uFeature);
// WRITEME
return rpcError (rpcNOT_SUPPORTED);
}
} // ripple

View File

@@ -0,0 +1,40 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doFetchInfo (Json::Value jvParams, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
Json::Value ret (Json::objectValue);
if (jvParams.isMember("clear") && jvParams["clear"].asBool())
{
mNetOps->clearLedgerFetch();
ret["clear"] = true;
}
ret["info"] = mNetOps->getLedgerFetchInfo();
return ret;
}
} // ripple

View File

@@ -0,0 +1,85 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// min_count: <number> // optional, defaults to 10
// }
Json::Value RPCHandler::doGetCounts (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
int minCount = 10;
if (params.isMember ("min_count"))
minCount = params["min_count"].asUInt ();
CountedObjects::List objectCounts = CountedObjects::getInstance ().getCounts (minCount);
Json::Value ret (Json::objectValue);
BOOST_FOREACH (CountedObjects::Entry& it, objectCounts)
{
ret [it.first] = it.second;
}
int dbKB = getApp().getLedgerDB ()->getDB ()->getKBUsedAll ();
if (dbKB > 0)
ret["dbKBTotal"] = dbKB;
dbKB = getApp().getLedgerDB ()->getDB ()->getKBUsedDB ();
if (dbKB > 0)
ret["dbKBLedger"] = dbKB;
dbKB = getApp().getTxnDB ()->getDB ()->getKBUsedDB ();
if (dbKB > 0)
ret["dbKBTransaction"] = dbKB;
{
std::size_t c = getApp().getOPs().getLocalTxCount ();
if (c > 0)
ret["local_txs"] = static_cast<Json::UInt> (c);
}
ret["write_load"] = getApp().getNodeStore ().getWriteLoad ();
ret["SLE_hit_rate"] = getApp().getSLECache ().getHitRate ();
ret["node_hit_rate"] = getApp().getNodeStore ().getCacheHitRate ();
ret["ledger_hit_rate"] = getApp().getLedgerMaster ().getCacheHitRate ();
ret["AL_hit_rate"] = AcceptedLedger::getCacheHitRate ();
ret["fullbelow_size"] = int(getApp().getFullBelowCache().size());
ret["treenode_size"] = SHAMap::getTreeNodeSize ();
std::string uptime;
int s = UptimeTimer::getInstance ().getElapsedSeconds ();
textTime (uptime, s, "year", 365 * 24 * 60 * 60);
textTime (uptime, s, "day", 24 * 60 * 60);
textTime (uptime, s, "hour", 60 * 60);
textTime (uptime, s, "minute", 60);
textTime (uptime, s, "second", 1);
ret["uptime"] = uptime;
return ret;
}
} // ripple

View File

@@ -0,0 +1,84 @@
//------------------------------------------------------------------------------
/*
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 {
// ledger [id|index|current|closed] [full]
// {
// ledger: 'current' | 'closed' | <uint256> | <number>, // optional
// full: true | false // optional, defaults to false.
// }
Json::Value RPCHandler::doLedger (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
if (!params.isMember ("ledger") && !params.isMember ("ledger_hash") && !params.isMember ("ledger_index"))
{
Json::Value ret (Json::objectValue), current (Json::objectValue), closed (Json::objectValue);
getApp().getLedgerMaster ().getCurrentLedger ()->addJson (current, 0);
getApp().getLedgerMaster ().getClosedLedger ()->addJson (closed, 0);
ret["open"] = current;
ret["closed"] = closed;
return ret;
}
Ledger::pointer lpLedger;
Json::Value jvResult = RPC::lookupLedger (params, lpLedger, *mNetOps);
if (!lpLedger)
return jvResult;
bool bFull = params.isMember ("full") && params["full"].asBool ();
bool bTransactions = params.isMember ("transactions") && params["transactions"].asBool ();
bool bAccounts = params.isMember ("accounts") && params["accounts"].asBool ();
bool bExpand = params.isMember ("expand") && params["expand"].asBool ();
int iOptions = (bFull ? LEDGER_JSON_FULL : 0)
| (bExpand ? LEDGER_JSON_EXPAND : 0)
| (bTransactions ? LEDGER_JSON_DUMP_TXRP : 0)
| (bAccounts ? LEDGER_JSON_DUMP_STATE : 0);
if (bFull || bAccounts)
{
if (mRole != Config::ADMIN)
{
// Until some sane way to get full ledgers has been implemented, disallow
// retrieving all state nodes
return rpcError (rpcNO_PERMISSION);
}
if (getApp().getFeeTrack().isLoadedLocal() && (mRole != Config::ADMIN))
{
WriteLog (lsDEBUG, Peer) << "Too busy to give full ledger";
return rpcError(rpcTOO_BUSY);
}
loadType = Resource::feeHighBurdenRPC;
}
Json::Value ret (Json::objectValue);
lpLedger->addJson (ret, iOptions);
return ret;
}
} // ripple

View File

@@ -0,0 +1,41 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doLedgerAccept (Json::Value, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
Json::Value jvResult;
if (!getConfig ().RUN_STANDALONE)
{
jvResult["error"] = "notStandAlone";
}
else
{
mNetOps->acceptLedger ();
jvResult["ledger_current_index"] = mNetOps->getCurrentLedgerID ();
}
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,31 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doLedgerCleaner (Json::Value parameters, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock();
getApp().getLedgerMaster().doLedgerCleaner (parameters);
return "Cleaner configured";
}
} // ripple

View File

@@ -0,0 +1,37 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doLedgerClosed (Json::Value, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
Json::Value jvResult;
uint256 uLedger = mNetOps->getClosedLedgerHash ();
jvResult["ledger_index"] = mNetOps->getLedgerID (uLedger);
jvResult["ledger_hash"] = to_string (uLedger);
//jvResult["ledger_time"] = uLedger.
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,33 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doLedgerCurrent (Json::Value, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
Json::Value jvResult;
jvResult["ledger_current_index"] = mNetOps->getCurrentLedgerID ();
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,119 @@
//------------------------------------------------------------------------------
/*
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 {
// Get state nodes from a ledger
// Inputs:
// limit: integer, maximum number of entries
// marker: opaque, resume point
// binary: boolean, format
// Outputs:
// ledger_hash: chosen ledger's hash
// ledger_index: chosen ledger's index
// state: array of state nodes
// marker: resume point, if any
Json::Value RPCHandler::doLedgerData (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
int const BINARY_PAGE_LENGTH = 256;
int const JSON_PAGE_LENGTH = 2048;
Ledger::pointer lpLedger;
Json::Value jvResult = RPC::lookupLedger (params, lpLedger, *mNetOps);
if (!lpLedger)
return jvResult;
uint256 resumePoint;
if (params.isMember ("marker"))
{
Json::Value const& jMarker = params["marker"];
if (!jMarker.isString ())
return RPC::expected_field_error ("marker", "valid");
if (!resumePoint.SetHex (jMarker.asString ()))
return RPC::expected_field_error ("marker", "valid");
}
bool isBinary = false;
if (params.isMember ("binary"))
{
Json::Value const& jBinary = params["binary"];
if (!jBinary.isBool ())
return RPC::expected_field_error ("binary", "bool");
isBinary = jBinary.asBool ();
}
int limit = -1;
int maxLimit = isBinary ? BINARY_PAGE_LENGTH : JSON_PAGE_LENGTH;
if (params.isMember ("limit"))
{
Json::Value const& jLimit = params["limit"];
if (!jLimit.isIntegral ())
return RPC::expected_field_error ("limit", "integer");
limit = jLimit.asInt ();
}
if ((limit < 0) || ((limit > maxLimit) && (mRole != Config::ADMIN)))
limit = maxLimit;
Json::Value jvReply = Json::objectValue;
jvReply["ledger_hash"] = to_string (lpLedger->getHash());
jvReply["ledger_index"] = beast::lexicalCastThrow <std::string> (lpLedger->getLedgerSeq ());
Json::Value& nodes = (jvReply["state"] = Json::arrayValue);
SHAMap& map = *(lpLedger->peekAccountStateMap ());
for (;;)
{
SHAMapItem::pointer item = map.peekNextItem (resumePoint);
if (!item)
break;
resumePoint = item->getTag();
if (limit-- <= 0)
{
--resumePoint;
jvReply["marker"] = to_string (resumePoint);
break;
}
if (isBinary)
{
Json::Value& entry = nodes.append (Json::objectValue);
entry["data"] = strHex (item->peekData().begin(), item->peekData().size());
entry["index"] = to_string (item->getTag ());
}
else
{
SLE sle (item->peekSerializer(), item->getTag ());
Json::Value& entry = nodes.append (sle.getJson (0));
entry["index"] = to_string (item->getTag ());
}
}
return jvReply;
}
} // ripple

View File

@@ -0,0 +1,229 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// ledger_hash : <ledger>
// ledger_index : <ledger_index>
// ...
// }
Json::Value RPCHandler::doLedgerEntry (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
Ledger::pointer lpLedger;
Json::Value jvResult = RPC::lookupLedger (params, lpLedger, *mNetOps);
if (!lpLedger)
return jvResult;
uint256 uNodeIndex;
bool bNodeBinary = false;
if (params.isMember ("index"))
{
// XXX Needs to provide proof.
uNodeIndex.SetHex (params["index"].asString ());
bNodeBinary = true;
}
else if (params.isMember ("account_root"))
{
RippleAddress naAccount;
if (!naAccount.setAccountID (params["account_root"].asString ())
|| !naAccount.getAccountID ())
{
jvResult["error"] = "malformedAddress";
}
else
{
uNodeIndex = Ledger::getAccountRootIndex (naAccount.getAccountID ());
}
}
else if (params.isMember ("directory"))
{
if (!params["directory"].isObject ())
{
uNodeIndex.SetHex (params["directory"].asString ());
}
else if (params["directory"].isMember ("sub_index")
&& !params["directory"]["sub_index"].isIntegral ())
{
jvResult["error"] = "malformedRequest";
}
else
{
std::uint64_t uSubIndex = params["directory"].isMember ("sub_index")
? params["directory"]["sub_index"].asUInt ()
: 0;
if (params["directory"].isMember ("dir_root"))
{
uint256 uDirRoot;
uDirRoot.SetHex (params["dir_root"].asString ());
uNodeIndex = Ledger::getDirNodeIndex (uDirRoot, uSubIndex);
}
else if (params["directory"].isMember ("owner"))
{
RippleAddress naOwnerID;
if (!naOwnerID.setAccountID (params["directory"]["owner"].asString ()))
{
jvResult["error"] = "malformedAddress";
}
else
{
uint256 uDirRoot = Ledger::getOwnerDirIndex (naOwnerID.getAccountID ());
uNodeIndex = Ledger::getDirNodeIndex (uDirRoot, uSubIndex);
}
}
else
{
jvResult["error"] = "malformedRequest";
}
}
}
else if (params.isMember ("generator"))
{
RippleAddress naGeneratorID;
if (!params["generator"].isObject ())
{
uNodeIndex.SetHex (params["generator"].asString ());
}
else if (!params["generator"].isMember ("regular_seed"))
{
jvResult["error"] = "malformedRequest";
}
else if (!naGeneratorID.setSeedGeneric (params["generator"]["regular_seed"].asString ()))
{
jvResult["error"] = "malformedAddress";
}
else
{
RippleAddress na0Public; // To find the generator's index.
RippleAddress naGenerator = RippleAddress::createGeneratorPublic (naGeneratorID);
na0Public.setAccountPublic (naGenerator, 0);
uNodeIndex = Ledger::getGeneratorIndex (na0Public.getAccountID ());
}
}
else if (params.isMember ("offer"))
{
RippleAddress naAccountID;
if (!params["offer"].isObject ())
{
uNodeIndex.SetHex (params["offer"].asString ());
}
else if (!params["offer"].isMember ("account")
|| !params["offer"].isMember ("seq")
|| !params["offer"]["seq"].isIntegral ())
{
jvResult["error"] = "malformedRequest";
}
else if (!naAccountID.setAccountID (params["offer"]["account"].asString ()))
{
jvResult["error"] = "malformedAddress";
}
else
{
std::uint32_t uSequence = params["offer"]["seq"].asUInt ();
uNodeIndex = Ledger::getOfferIndex (naAccountID.getAccountID (), uSequence);
}
}
else if (params.isMember ("ripple_state"))
{
RippleAddress naA;
RippleAddress naB;
uint160 uCurrency;
Json::Value jvRippleState = params["ripple_state"];
if (!jvRippleState.isObject ()
|| !jvRippleState.isMember ("currency")
|| !jvRippleState.isMember ("accounts")
|| !jvRippleState["accounts"].isArray ()
|| 2 != jvRippleState["accounts"].size ()
|| !jvRippleState["accounts"][0u].isString ()
|| !jvRippleState["accounts"][1u].isString ()
|| jvRippleState["accounts"][0u].asString () == jvRippleState["accounts"][1u].asString ()
)
{
jvResult["error"] = "malformedRequest";
}
else if (!naA.setAccountID (jvRippleState["accounts"][0u].asString ())
|| !naB.setAccountID (jvRippleState["accounts"][1u].asString ()))
{
jvResult["error"] = "malformedAddress";
}
else if (!STAmount::currencyFromString (uCurrency, jvRippleState["currency"].asString ()))
{
jvResult["error"] = "malformedCurrency";
}
else
{
uNodeIndex = Ledger::getRippleStateIndex (naA, naB, uCurrency);
}
}
else
{
jvResult["error"] = "unknownOption";
}
if (uNodeIndex.isNonZero ())
{
SLE::pointer sleNode = mNetOps->getSLEi (lpLedger, uNodeIndex);
if (params.isMember("binary"))
bNodeBinary = params["binary"].asBool();
if (!sleNode)
{
// Not found.
// XXX Should also provide proof.
jvResult["error"] = "entryNotFound";
}
else if (bNodeBinary)
{
// XXX Should also provide proof.
Serializer s;
sleNode->add (s);
jvResult["node_binary"] = strHex (s.peekData ());
jvResult["index"] = to_string (uNodeIndex);
}
else
{
jvResult["node"] = sleNode->getJson (0);
jvResult["index"] = to_string (uNodeIndex);
}
}
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,50 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// ledger_hash : <ledger>
// ledger_index : <ledger_index>
// }
Json::Value RPCHandler::doLedgerHeader (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
Ledger::pointer lpLedger;
Json::Value jvResult = RPC::lookupLedger (params, lpLedger, *mNetOps);
if (!lpLedger)
return jvResult;
Serializer s;
lpLedger->addRaw (s);
jvResult["ledger_data"] = strHex (s.peekData ());
// This information isn't verified, they should only use it if they trust us.
lpLedger->addJson (jvResult, 0);
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,72 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doLogLevel (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
// log_level
if (!params.isMember ("severity"))
{
// get log severities
Json::Value ret (Json::objectValue);
Json::Value lev (Json::objectValue);
lev["base"] = Log::severityToString (LogSink::get()->getMinSeverity ());
std::vector< std::pair<std::string, std::string> > logTable = LogPartition::getSeverities ();
typedef std::map<std::string, std::string>::value_type stringPair;
BOOST_FOREACH (const stringPair & it, logTable)
lev[it.first] = it.second;
ret["levels"] = lev;
return ret;
}
LogSeverity sv = Log::stringToSeverity (params["severity"].asString ());
if (sv == lsINVALID)
return rpcError (rpcINVALID_PARAMS);
// log_level severity
if (!params.isMember ("partition"))
{
// set base log severity
LogSink::get()->setMinSeverity (sv, true);
return Json::objectValue;
}
// log_level partition severity base?
if (params.isMember ("partition"))
{
// set partition severity
std::string partition (params["partition"].asString ());
if (boost::iequals (partition, "base"))
LogSink::get()->setMinSeverity (sv, false);
else if (!LogPartition::setSeverity (partition, sv))
return rpcError (rpcINVALID_PARAMS);
return Json::objectValue;
}
return rpcError (rpcINVALID_PARAMS);
}
} // ripple

View File

@@ -0,0 +1,29 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doLogRotate (Json::Value, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
return LogSink::get()->rotateLog ();
}
} // ripple

View File

@@ -0,0 +1,54 @@
//------------------------------------------------------------------------------
/*
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 {
#if 0
// XXX Needs to be revised for new paradigm
// nickname_info <nickname>
// Note: Nicknames are not automatically looked up by commands as they are advisory and can be changed.
Json::Value RPCHandler::doNicknameInfo (Json::Value params)
{
std::string strNickname = params[0u].asString ();
boost::trim (strNickname);
if (strNickname.empty ())
{
return rpcError (rpcNICKNAME_MALFORMED);
}
NicknameState::pointer nsSrc = mNetOps->getNicknameState (uint256 (0), strNickname);
if (!nsSrc)
{
return rpcError (rpcNICKNAME_MISSING);
}
Json::Value ret (Json::objectValue);
ret["nickname"] = strNickname;
nsSrc->addJson (ret);
return ret;
}
#endif
} // ripple

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.
*/
//==============================================================================
namespace ripple {
// {
// 'ident' : <indent>,
// 'account_index' : <index> // optional
// }
// XXX This would be better if it took the ledger.
Json::Value RPCHandler::doOwnerInfo (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
if (!params.isMember ("account") && !params.isMember ("ident"))
return RPC::missing_field_error ("account");
std::string strIdent = params.isMember ("account") ? params["account"].asString () : params["ident"].asString ();
bool bIndex;
int iIndex = params.isMember ("account_index") ? params["account_index"].asUInt () : 0;
RippleAddress raAccount;
Json::Value ret;
// Get info on account.
Json::Value jAccepted = RPC::accountFromString (mNetOps->getClosedLedger (), raAccount, bIndex, strIdent, iIndex, false, *mNetOps);
ret["accepted"] = jAccepted.empty () ? mNetOps->getOwnerInfo (mNetOps->getClosedLedger (), raAccount) : jAccepted;
Json::Value jCurrent = RPC::accountFromString (mNetOps->getCurrentLedger (), raAccount, bIndex, strIdent, iIndex, false, *mNetOps);
ret["current"] = jCurrent.empty () ? mNetOps->getOwnerInfo (mNetOps->getCurrentLedger (), raAccount) : jCurrent;
return ret;
}
} // ripple

View File

@@ -0,0 +1,67 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doPathFind (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
Ledger::pointer lpLedger = mNetOps->getClosedLedger();
masterLockHolder.unlock();
if (!params.isMember ("subcommand") || !params["subcommand"].isString ())
return rpcError (rpcINVALID_PARAMS);
if (!mInfoSub)
return rpcError (rpcNO_EVENTS);
std::string sSubCommand = params["subcommand"].asString ();
if (sSubCommand == "create")
{
loadType = Resource::feeHighBurdenRPC;
mInfoSub->clearPathRequest ();
return getApp().getPathRequests().makePathRequest (mInfoSub, lpLedger, params);
}
if (sSubCommand == "close")
{
PathRequest::pointer request = mInfoSub->getPathRequest ();
if (!request)
return rpcError (rpcNO_PF_REQUEST);
mInfoSub->clearPathRequest ();
return request->doClose (params);
}
if (sSubCommand == "status")
{
PathRequest::pointer request = mInfoSub->getPathRequest ();
if (!request)
return rpcNO_PF_REQUEST;
return request->doStatus (params);
}
return rpcError (rpcINVALID_PARAMS);
}
} // ripple

View File

@@ -0,0 +1,35 @@
//------------------------------------------------------------------------------
/*
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/overlay/api/Overlay.h>
namespace ripple {
Json::Value RPCHandler::doPeers (Json::Value, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
Json::Value jvResult (Json::objectValue);
jvResult["peers"] = getApp().overlay ().json ();
getApp().getUNL().addClusterStatus(jvResult);
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,28 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doPing (Json::Value, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
return Json::Value (Json::objectValue);
}
} // ripple

View File

@@ -0,0 +1,36 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doPrint (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
JsonPropertyStream stream;
if (params.isObject() && params["params"].isArray() && params["params"][0u].isString ())
getApp().write (stream, params["params"][0u].asString());
else
getApp().write (stream);
return stream.top();
}
} // ripple

View File

@@ -0,0 +1,115 @@
//------------------------------------------------------------------------------
/*
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 RPCHandler::doProfile (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
/* need to fix now that sharedOfferCreate is gone
int iArgs = params.size();
RippleAddress naSeedA;
RippleAddress naAccountA;
uint160 uCurrencyOfferA;
RippleAddress naSeedB;
RippleAddress naAccountB;
uint160 uCurrencyOfferB;
uint32 iCount = 100;
bool bSubmit = false;
if (iArgs < 6 || "offers" != params[0u].asString())
{
return rpcError(rpcINVALID_PARAMS);
}
if (!naSeedA.setSeedGeneric(params[1u].asString())) // <pass_a>
return rpcError(rpcINVALID_PARAMS);
naAccountA.setAccountID(params[2u].asString()); // <account_a>
if (!STAmount::currencyFromString(uCurrencyOfferA, params[3u].asString())) // <currency_offer_a>
return rpcError(rpcINVALID_PARAMS);
naAccountB.setAccountID(params[4u].asString()); // <account_b>
if (!STAmount::currencyFromString(uCurrencyOfferB, params[5u].asString())) // <currency_offer_b>
return rpcError(rpcINVALID_PARAMS);
iCount = lexicalCast <uint32>(params[6u].asString());
if (iArgs >= 8 && "false" != params[7u].asString())
bSubmit = true;
LogSink::get()->setMinSeverity(lsFATAL,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 = mNetOps->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

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// // if either of these parameters is set, a custom generator is used
// difficulty: <number> // optional
// secret: <secret> // optional
// }
Json::Value RPCHandler::doProofCreate (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
// XXX: Add ability to create proof with arbitrary time
Json::Value jvResult (Json::objectValue);
if (params.isMember ("difficulty") || params.isMember ("secret"))
{
// VFALCO TODO why aren't we using the app's factory?
std::unique_ptr <ProofOfWorkFactory> pgGen (ProofOfWorkFactory::New ());
if (params.isMember ("difficulty"))
{
if (!params["difficulty"].isIntegral ())
return RPC::invalid_field_error ("difficulty");
int const iDifficulty (params["difficulty"].asInt ());
if (iDifficulty < 0 || iDifficulty > ProofOfWorkFactory::kMaxDifficulty)
return RPC::invalid_field_error ("difficulty");
pgGen->setDifficulty (iDifficulty);
}
if (params.isMember ("secret"))
{
uint256 uSecret (params["secret"].asString ());
pgGen->setSecret (uSecret);
}
jvResult["token"] = pgGen->getProof ().getToken ();
jvResult["secret"] = to_string (pgGen->getSecret ());
}
else
{
jvResult["token"] = getApp().getProofOfWorkFactory ().getProof ().getToken ();
}
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,48 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// token: <token>
// }
Json::Value RPCHandler::doProofSolve (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
Json::Value jvResult;
if (!params.isMember ("token"))
return RPC::missing_field_error ("token");
std::string strToken = params["token"].asString ();
if (!ProofOfWork::validateToken (strToken))
return RPC::invalid_field_error ("token");
ProofOfWork powProof (strToken);
uint256 uSolution = powProof.solve ();
jvResult["solution"] = to_string (uSolution);
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,94 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// token: <token>
// solution: <solution>
// // if either of these parameters is set, a custom verifier is used
// difficulty: <number> // optional
// secret: <secret> // optional
// }
Json::Value RPCHandler::doProofVerify (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
// XXX Add ability to check proof against arbitrary time
Json::Value jvResult;
if (!params.isMember ("token"))
return RPC::missing_field_error ("token");
if (!params.isMember ("solution"))
return RPC::missing_field_error ("solution");
std::string strToken = params["token"].asString ();
uint256 uSolution (params["solution"].asString ());
PowResult prResult;
if (params.isMember ("difficulty") || params.isMember ("secret"))
{
// VFALCO TODO why aren't we using the app's factory?
std::unique_ptr <ProofOfWorkFactory> pgGen (ProofOfWorkFactory::New ());
if (params.isMember ("difficulty"))
{
if (!params["difficulty"].isIntegral ())
return RPC::invalid_field_error ("difficulty");
int iDifficulty = params["difficulty"].asInt ();
if (iDifficulty < 0 || iDifficulty > ProofOfWorkFactory::kMaxDifficulty)
return RPC::missing_field_error ("difficulty");
pgGen->setDifficulty (iDifficulty);
}
if (params.isMember ("secret"))
{
uint256 uSecret (params["secret"].asString ());
pgGen->setSecret (uSecret);
}
prResult = pgGen->checkProof (strToken, uSolution);
jvResult["secret"] = to_string (pgGen->getSecret ());
}
else
{
// XXX Proof should not be marked as used from this
prResult = getApp().getProofOfWorkFactory ().checkProof (strToken, uSolution);
}
std::string sToken;
std::string sHuman;
ProofOfWork::calcResultInfo (prResult, sToken, sHuman);
jvResult["proof_result"] = sToken;
jvResult["proof_result_code"] = prResult;
jvResult["proof_result_message"] = sHuman;
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,48 @@
//------------------------------------------------------------------------------
/*
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 {
// Result:
// {
// random: <uint256>
// }
Json::Value RPCHandler::doRandom (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
uint256 uRandom;
try
{
RandomNumbers::getInstance ().fillBytes (uRandom.begin (), uRandom.size ());
Json::Value jvResult;
jvResult["random"] = to_string (uRandom);
return jvResult;
}
catch (...)
{
return rpcError (rpcINTERNAL);
}
}
} // ripple

View File

@@ -0,0 +1,305 @@
//------------------------------------------------------------------------------
/*
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/impl/LegacyPathFind.h>
namespace ripple {
// This interface is deprecated.
Json::Value RPCHandler::doRipplePathFind (
Json::Value params, Resource::Charge& loadType,
Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
RPC::LegacyPathFind lpf (mRole == Config::ADMIN);
if (!lpf.isOk ())
return rpcError (rpcTOO_BUSY);
loadType = Resource::feeHighBurdenRPC;
RippleAddress raSrc;
RippleAddress raDst;
STAmount saDstAmount;
Ledger::pointer lpLedger;
Json::Value jvResult;
if (getConfig().RUN_STANDALONE || params.isMember("ledger") || params.isMember("ledger_index") || params.isMember("ledger_hash"))
{ // The caller specified a ledger
jvResult = RPC::lookupLedger (params, lpLedger, *mNetOps);
if (!lpLedger)
return jvResult;
}
if (!params.isMember ("source_account"))
{
jvResult = rpcError (rpcSRC_ACT_MISSING);
}
else if (!params["source_account"].isString ()
|| !raSrc.setAccountID (params["source_account"].asString ()))
{
jvResult = rpcError (rpcSRC_ACT_MALFORMED);
}
else if (!params.isMember ("destination_account"))
{
jvResult = rpcError (rpcDST_ACT_MISSING);
}
else if (!params["destination_account"].isString ()
|| !raDst.setAccountID (params["destination_account"].asString ()))
{
jvResult = rpcError (rpcDST_ACT_MALFORMED);
}
else if (
// Parse saDstAmount.
!params.isMember ("destination_amount")
|| !saDstAmount.bSetJson (params["destination_amount"])
|| saDstAmount <= zero
|| (!!saDstAmount.getCurrency () && (!saDstAmount.getIssuer () || ACCOUNT_ONE == saDstAmount.getIssuer ())))
{
WriteLog (lsINFO, RPCHandler) << "Bad destination_amount.";
jvResult = rpcError (rpcINVALID_PARAMS);
}
else if (
// Checks on source_currencies.
params.isMember ("source_currencies")
&& (!params["source_currencies"].isArray ()
|| !params["source_currencies"].size ()) // Don't allow empty currencies.
)
{
WriteLog (lsINFO, RPCHandler) << "Bad source_currencies.";
jvResult = rpcError (rpcINVALID_PARAMS);
}
else
{
loadType = Resource::feeHighBurdenRPC;
RippleLineCache::pointer cache;
if (lpLedger)
{
// The caller specified a ledger
lpLedger = boost::make_shared<Ledger> (boost::ref (*lpLedger), false);
cache = boost::make_shared<RippleLineCache>(lpLedger);
}
else
{
// The closed ledger is recent and any nodes made resident
// have the best chance to persist
lpLedger = mNetOps->getClosedLedger();
cache = getApp().getPathRequests().getLineCache(lpLedger, false);
}
Json::Value jvSrcCurrencies;
if (params.isMember ("source_currencies"))
{
jvSrcCurrencies = params["source_currencies"];
}
else
{
boost::unordered_set<uint160> usCurrencies = usAccountSourceCurrencies (raSrc, cache, true);
jvSrcCurrencies = Json::Value (Json::arrayValue);
BOOST_FOREACH (const uint160 & uCurrency, usCurrencies)
{
Json::Value jvCurrency (Json::objectValue);
jvCurrency["currency"] = STAmount::createHumanCurrency (uCurrency);
jvSrcCurrencies.append (jvCurrency);
}
}
// Fill in currencies destination will accept
Json::Value jvDestCur (Json::arrayValue);
boost::unordered_set<uint160> usDestCurrID = usAccountDestCurrencies (raDst, cache, true);
BOOST_FOREACH (const uint160 & uCurrency, usDestCurrID)
jvDestCur.append (STAmount::createHumanCurrency (uCurrency));
jvResult["destination_currencies"] = jvDestCur;
jvResult["destination_account"] = raDst.humanAccountID ();
Json::Value jvArray (Json::arrayValue);
for (unsigned int i = 0; i != jvSrcCurrencies.size (); ++i)
{
Json::Value jvSource = jvSrcCurrencies[i];
uint160 uSrcCurrencyID;
uint160 uSrcIssuerID;
if (!jvSource.isObject ())
return rpcError (rpcINVALID_PARAMS);
// Parse mandatory currency.
if (!jvSource.isMember ("currency")
|| !STAmount::currencyFromString (uSrcCurrencyID, jvSource["currency"].asString ()))
{
WriteLog (lsINFO, RPCHandler) << "Bad currency.";
return rpcError (rpcSRC_CUR_MALFORMED);
}
if (uSrcCurrencyID.isNonZero ())
uSrcIssuerID = raSrc.getAccountID ();
// Parse optional issuer.
if (jvSource.isMember ("issuer") &&
((!jvSource["issuer"].isString () ||
!STAmount::issuerFromString (uSrcIssuerID, jvSource["issuer"].asString ())) ||
(uSrcIssuerID.isZero () != uSrcCurrencyID.isZero ()) ||
(ACCOUNT_ONE == uSrcIssuerID)))
{
WriteLog (lsINFO, RPCHandler) << "Bad issuer.";
return rpcError (rpcSRC_ISR_MALFORMED);
}
STPathSet spsComputed;
bool bValid;
Pathfinder pf (cache, raSrc, raDst, uSrcCurrencyID, uSrcIssuerID, saDstAmount, bValid);
int level = getConfig().PATH_SEARCH_OLD;
if ((getConfig().PATH_SEARCH_MAX > level) && !getApp().getFeeTrack().isLoadedLocal())
++level;
if (params.isMember("depth") && params["depth"].isIntegral())
{
int rLev = params["search_depth"].asInt ();
if ((rLev < level) || (mRole == Config::ADMIN))
level = rLev;
}
if (params.isMember("paths"))
{
STParsedJSON paths ("paths", params["paths"]);
if (paths.object.get() == nullptr)
return paths.error;
else
spsComputed = paths.object.get()->downcast<STPathSet> ();
}
STPath extraPath;
if (!bValid || !pf.findPaths (level, 4, spsComputed, extraPath))
{
WriteLog (lsWARNING, RPCHandler) << "ripple_path_find: No paths found.";
}
else
{
std::vector<PathState::pointer> vpsExpanded;
STAmount saMaxAmountAct;
STAmount saDstAmountAct;
STAmount saMaxAmount (
uSrcCurrencyID,
!!uSrcIssuerID
? uSrcIssuerID // Use specifed issuer.
: !!uSrcCurrencyID // Default to source account.
? raSrc.getAccountID ()
: ACCOUNT_XRP,
1);
saMaxAmount.negate ();
LedgerEntrySet lesSandbox (lpLedger, tapNONE);
TER terResult =
rippleCalculate (
lesSandbox,
saMaxAmountAct, // <--
saDstAmountAct, // <--
vpsExpanded, // <--
saMaxAmount, // --> Amount to send is unlimited to get an estimate.
saDstAmount, // --> Amount to deliver.
raDst.getAccountID (), // --> Account to deliver to.
raSrc.getAccountID (), // --> Account sending from.
spsComputed, // --> Path set.
false, // --> Don't allow partial payment. This is for normal fill or kill payments.
// Must achieve delivery goal.
false, // --> Don't limit quality. Average quality is wanted for normal payments.
false, // --> Allow direct ripple to be added to path set. to path set.
true); // --> Stand alone mode, no point in deleting unfundeds.
// WriteLog (lsDEBUG, RPCHandler) << "ripple_path_find: PATHS IN: " << spsComputed.size() << " : " << spsComputed.getJson(0);
// WriteLog (lsDEBUG, RPCHandler) << "ripple_path_find: PATHS EXP: " << vpsExpanded.size();
WriteLog (lsWARNING, RPCHandler)
<< boost::str (boost::format ("ripple_path_find: saMaxAmount=%s saDstAmount=%s saMaxAmountAct=%s saDstAmountAct=%s")
% saMaxAmount
% saDstAmount
% saMaxAmountAct
% saDstAmountAct);
if ((extraPath.size() > 0) && ((terResult == terNO_LINE) || (terResult == tecPATH_PARTIAL)))
{
WriteLog (lsDEBUG, PathRequest) << "Trying with an extra path element";
spsComputed.addPath(extraPath);
vpsExpanded.clear ();
lesSandbox.clear ();
terResult = rippleCalculate (lesSandbox, saMaxAmountAct, saDstAmountAct,
vpsExpanded, saMaxAmount, saDstAmount,
raDst.getAccountID (), raSrc.getAccountID (),
spsComputed, false, false, false, true);
WriteLog (lsDEBUG, PathRequest) << "Extra path element gives " << transHuman (terResult);
}
if (tesSUCCESS == terResult)
{
Json::Value jvEntry (Json::objectValue);
STPathSet spsCanonical;
// Reuse the expanded as it would need to be calcuated anyway to produce the canonical.
// (At least unless we make a direct canonical.)
// RippleCalc::setCanonical(spsCanonical, vpsExpanded, false);
jvEntry["source_amount"] = saMaxAmountAct.getJson (0);
// jvEntry["paths_expanded"] = vpsExpanded.getJson(0);
jvEntry["paths_canonical"] = Json::arrayValue; // spsCanonical.getJson(0);
jvEntry["paths_computed"] = spsComputed.getJson (0);
jvArray.append (jvEntry);
}
else
{
std::string strToken;
std::string strHuman;
transResultInfo (terResult, strToken, strHuman);
WriteLog (lsDEBUG, RPCHandler)
<< boost::str (boost::format ("ripple_path_find: %s %s %s")
% strToken
% strHuman
% spsComputed.getJson (0));
}
}
}
// Each alternative differs by source currency.
jvResult["alternatives"] = jvArray;
}
WriteLog (lsDEBUG, RPCHandler)
<< boost::str (boost::format ("ripple_path_find< %s")
% jvResult);
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,34 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doSMS (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
if (!params.isMember ("text"))
return rpcError (rpcINVALID_PARAMS);
HTTPClient::sendSMS (getApp().getIOService (), params["text"].asString ());
return "sms dispatched";
}
} // ripple

View File

@@ -0,0 +1,32 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doServerInfo (Json::Value, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
Json::Value ret (Json::objectValue);
ret["info"] = mNetOps->getServerInfo (true, mRole == Config::ADMIN);
return ret;
}
} // ripple

View File

@@ -0,0 +1,32 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doServerState (Json::Value, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
Json::Value ret (Json::objectValue);
ret["state"] = mNetOps->getServerInfo (false, mRole == Config::ADMIN);
return ret;
}
} // ripple

View File

@@ -0,0 +1,36 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// tx_json: <object>,
// secret: <secret>
// }
Json::Value RPCHandler::doSign (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
loadType = Resource::feeHighBurdenRPC;
bool bFailHard = params.isMember ("fail_hard") && params["fail_hard"].asBool ();
return RPC::transactionSign (params, false, bFailHard, masterLockHolder, *mNetOps, mRole);
}
} // ripple

View File

@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doStop (Json::Value, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
getApp().signalStop ();
return SYSTEM_NAME " server stopping";
}
} // ripple

View File

@@ -0,0 +1,119 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// tx_json: <object>,
// secret: <secret>
// }
Json::Value RPCHandler::doSubmit (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
loadType = Resource::feeMediumBurdenRPC;
if (!params.isMember ("tx_blob"))
{
bool bFailHard = params.isMember ("fail_hard") && params["fail_hard"].asBool ();
return RPC::transactionSign (params, true, bFailHard, masterLockHolder, *mNetOps, mRole);
}
Json::Value jvResult;
std::pair<Blob, bool> ret(strUnHex (params["tx_blob"].asString ()));
if (!ret.second || !ret.first.size ())
return rpcError (rpcINVALID_PARAMS);
Serializer sTrans (ret.first);
SerializerIterator sitTrans (sTrans);
SerializedTransaction::pointer stpTrans;
try
{
stpTrans = boost::make_shared<SerializedTransaction> (boost::ref (sitTrans));
}
catch (std::exception& e)
{
jvResult[jss::error] = "invalidTransaction";
jvResult["error_exception"] = e.what ();
return jvResult;
}
Transaction::pointer tpTrans;
try
{
tpTrans = boost::make_shared<Transaction> (stpTrans, false);
}
catch (std::exception& e)
{
jvResult[jss::error] = "internalTransaction";
jvResult["error_exception"] = e.what ();
return jvResult;
}
try
{
(void) mNetOps->processTransaction (tpTrans, mRole == Config::ADMIN, true,
params.isMember ("fail_hard") && params["fail_hard"].asBool ());
}
catch (std::exception& e)
{
jvResult[jss::error] = "internalSubmit";
jvResult[jss::error_exception] = e.what ();
return jvResult;
}
try
{
jvResult[jss::tx_json] = tpTrans->getJson (0);
jvResult[jss::tx_blob] = strHex (tpTrans->getSTransaction ()->getSerializer ().peekData ());
if (temUNCERTAIN != tpTrans->getResult ())
{
std::string sToken;
std::string sHuman;
transResultInfo (tpTrans->getResult (), sToken, sHuman);
jvResult[jss::engine_result] = sToken;
jvResult[jss::engine_result_code] = tpTrans->getResult ();
jvResult[jss::engine_result_message] = sHuman;
}
return jvResult;
}
catch (std::exception& e)
{
jvResult[jss::error] = "internalJson";
jvResult[jss::error_exception] = e.what ();
return jvResult;
}
}
} // ripple

View File

@@ -0,0 +1,332 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doSubscribe (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
// FIXME: This needs to release the master lock immediately
// Subscriptions need to be protected by their own lock
InfoSub::pointer ispSub;
Json::Value jvResult (Json::objectValue);
std::uint32_t uLedgerIndex = params.isMember (jss::ledger_index) && params[jss::ledger_index].isNumeric ()
? params[jss::ledger_index].asUInt ()
: 0;
if (!mInfoSub && !params.isMember ("url"))
{
// Must be a JSON-RPC call.
WriteLog (lsINFO, RPCHandler) << boost::str (boost::format ("doSubscribe: RPC subscribe requires a url"));
return rpcError (rpcINVALID_PARAMS);
}
if (params.isMember ("url"))
{
if (mRole != Config::ADMIN)
return rpcError (rpcNO_PERMISSION);
std::string strUrl = params["url"].asString ();
std::string strUsername = params.isMember ("url_username") ? params["url_username"].asString () : "";
std::string strPassword = params.isMember ("url_password") ? params["url_password"].asString () : "";
// DEPRECATED
if (params.isMember ("username"))
strUsername = params["username"].asString ();
// DEPRECATED
if (params.isMember ("password"))
strPassword = params["password"].asString ();
ispSub = mNetOps->findRpcSub (strUrl);
if (!ispSub)
{
WriteLog (lsDEBUG, RPCHandler) << boost::str (boost::format ("doSubscribe: building: %s") % strUrl);
RPCSub::pointer rspSub = RPCSub::New (getApp ().getOPs (),
getApp ().getIOService (), getApp ().getJobQueue (),
strUrl, strUsername, strPassword);
ispSub = mNetOps->addRpcSub (strUrl, boost::dynamic_pointer_cast<InfoSub> (rspSub));
}
else
{
WriteLog (lsTRACE, RPCHandler) << boost::str (boost::format ("doSubscribe: reusing: %s") % strUrl);
if (params.isMember ("username"))
dynamic_cast<RPCSub*> (&*ispSub)->setUsername (strUsername);
if (params.isMember ("password"))
dynamic_cast<RPCSub*> (&*ispSub)->setPassword (strPassword);
}
}
else
{
ispSub = mInfoSub;
}
if (!params.isMember ("streams"))
{
nothing ();
}
else if (!params["streams"].isArray ())
{
WriteLog (lsINFO, RPCHandler) << boost::str (boost::format ("doSubscribe: streams requires an array."));
return rpcError (rpcINVALID_PARAMS);
}
else
{
for (Json::Value::iterator it = params["streams"].begin (); it != params["streams"].end (); it++)
{
if ((*it).isString ())
{
std::string streamName = (*it).asString ();
if (streamName == "server")
{
mNetOps->subServer (ispSub, jvResult);
}
else if (streamName == "ledger")
{
mNetOps->subLedger (ispSub, jvResult);
}
else if (streamName == "transactions")
{
mNetOps->subTransactions (ispSub);
}
else if (streamName == "transactions_proposed"
|| streamName == "rt_transactions") // DEPRECATED
{
mNetOps->subRTTransactions (ispSub);
}
else
{
jvResult[jss::error] = "unknownStream";
}
}
else
{
jvResult[jss::error] = "malformedStream";
}
}
}
std::string strAccountsProposed = params.isMember ("accounts_proposed")
? "accounts_proposed"
: "rt_accounts"; // DEPRECATED
if (!params.isMember (strAccountsProposed))
{
nothing ();
}
else if (!params[strAccountsProposed].isArray ())
{
return rpcError (rpcINVALID_PARAMS);
}
else
{
boost::unordered_set<RippleAddress> usnaAccoundIds = RPC::parseAccountIds (params[strAccountsProposed]);
if (usnaAccoundIds.empty ())
{
jvResult[jss::error] = "malformedAccount";
}
else
{
mNetOps->subAccount (ispSub, usnaAccoundIds, uLedgerIndex, true);
}
}
if (!params.isMember ("accounts"))
{
nothing ();
}
else if (!params["accounts"].isArray ())
{
return rpcError (rpcINVALID_PARAMS);
}
else
{
boost::unordered_set<RippleAddress> usnaAccoundIds = RPC::parseAccountIds (params["accounts"]);
if (usnaAccoundIds.empty ())
{
jvResult[jss::error] = "malformedAccount";
}
else
{
mNetOps->subAccount (ispSub, usnaAccoundIds, uLedgerIndex, false);
WriteLog (lsDEBUG, RPCHandler) << boost::str (boost::format ("doSubscribe: accounts: %d") % usnaAccoundIds.size ());
}
}
bool bHaveMasterLock = true;
if (!params.isMember ("books"))
{
nothing ();
}
else if (!params["books"].isArray ())
{
return rpcError (rpcINVALID_PARAMS);
}
else
{
for (Json::Value::iterator it = params["books"].begin (); it != params["books"].end (); it++)
{
Json::Value& jvSubRequest = *it;
if (!jvSubRequest.isObject ()
|| !jvSubRequest.isMember (jss::taker_pays)
|| !jvSubRequest.isMember (jss::taker_gets)
|| !jvSubRequest[jss::taker_pays].isObject ()
|| !jvSubRequest[jss::taker_gets].isObject ())
return rpcError (rpcINVALID_PARAMS);
// VFALCO TODO Use RippleAsset here
RippleCurrency pay_currency;
RippleIssuer pay_issuer;
RippleCurrency get_currency;
RippleIssuer get_issuer;
bool bBoth = (jvSubRequest.isMember ("both") && jvSubRequest["both"].asBool ())
|| (jvSubRequest.isMember ("both_sides") && jvSubRequest["both_sides"].asBool ()); // DEPRECATED
bool bSnapshot = (jvSubRequest.isMember ("snapshot") && jvSubRequest["snapshot"].asBool ())
|| (jvSubRequest.isMember ("state_now") && jvSubRequest["state_now"].asBool ()); // DEPRECATED
Json::Value taker_pays = jvSubRequest[jss::taker_pays];
Json::Value taker_gets = jvSubRequest[jss::taker_gets];
// Parse mandatory currency.
if (!taker_pays.isMember (jss::currency)
|| !STAmount::currencyFromString (pay_currency, taker_pays[jss::currency].asString ()))
{
WriteLog (lsINFO, RPCHandler) << "Bad taker_pays currency.";
return rpcError (rpcSRC_CUR_MALFORMED);
}
// Parse optional issuer.
else if (((taker_pays.isMember (jss::issuer))
&& (!taker_pays[jss::issuer].isString ()
|| !STAmount::issuerFromString (pay_issuer, taker_pays[jss::issuer].asString ())))
// Don't allow illegal issuers.
|| (!pay_currency != !pay_issuer)
|| ACCOUNT_ONE == pay_issuer)
{
WriteLog (lsINFO, RPCHandler) << "Bad taker_pays issuer.";
return rpcError (rpcSRC_ISR_MALFORMED);
}
// Parse mandatory currency.
if (!taker_gets.isMember (jss::currency)
|| !STAmount::currencyFromString (get_currency, taker_gets[jss::currency].asString ()))
{
WriteLog (lsINFO, RPCHandler) << "Bad taker_pays currency.";
return rpcError (rpcSRC_CUR_MALFORMED);
}
// Parse optional issuer.
else if (((taker_gets.isMember (jss::issuer))
&& (!taker_gets[jss::issuer].isString ()
|| !STAmount::issuerFromString (get_issuer, taker_gets[jss::issuer].asString ())))
// Don't allow illegal issuers.
|| (!get_currency != !get_issuer)
|| ACCOUNT_ONE == get_issuer)
{
WriteLog (lsINFO, RPCHandler) << "Bad taker_gets issuer.";
return rpcError (rpcDST_ISR_MALFORMED);
}
if (pay_currency == get_currency
&& pay_issuer == get_issuer)
{
WriteLog (lsINFO, RPCHandler) << "taker_gets same as taker_pays.";
return rpcError (rpcBAD_MARKET);
}
RippleAddress raTakerID;
if (!jvSubRequest.isMember ("taker"))
{
raTakerID.setAccountID (ACCOUNT_ONE);
}
else if (!raTakerID.setAccountID (jvSubRequest["taker"].asString ()))
{
return rpcError (rpcBAD_ISSUER);
}
if (!Ledger::isValidBook (pay_currency, pay_issuer, get_currency, get_issuer))
{
WriteLog (lsWARNING, RPCHandler) << "Bad market: " <<
pay_currency << ":" << pay_issuer << " -> " <<
get_currency << ":" << get_issuer;
return rpcError (rpcBAD_MARKET);
}
mNetOps->subBook (ispSub, pay_currency, get_currency, pay_issuer, get_issuer);
if (bBoth) mNetOps->subBook (ispSub, get_currency, pay_currency, get_issuer, pay_issuer);
if (bSnapshot)
{
if (bHaveMasterLock)
{
masterLockHolder.unlock ();
bHaveMasterLock = false;
}
loadType = Resource::feeMediumBurdenRPC;
Ledger::pointer lpLedger = getApp().getLedgerMaster ().getPublishedLedger ();
if (lpLedger)
{
const Json::Value jvMarker = Json::Value (Json::nullValue);
if (bBoth)
{
Json::Value jvBids (Json::objectValue);
Json::Value jvAsks (Json::objectValue);
mNetOps->getBookPage (lpLedger, pay_currency, pay_issuer, get_currency, get_issuer, raTakerID.getAccountID (), false, 0, jvMarker, jvBids);
if (jvBids.isMember (jss::offers)) jvResult[jss::bids] = jvBids[jss::offers];
mNetOps->getBookPage (lpLedger, get_currency, get_issuer, pay_currency, pay_issuer, raTakerID.getAccountID (), false, 0, jvMarker, jvAsks);
if (jvAsks.isMember (jss::offers)) jvResult[jss::asks] = jvAsks[jss::offers];
}
else
{
mNetOps->getBookPage (lpLedger, pay_currency, pay_issuer, get_currency, get_issuer, raTakerID.getAccountID (), false, 0, jvMarker, jvResult);
}
}
}
}
}
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,82 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// ledger_hash : <ledger>,
// ledger_index : <ledger_index>
// }
// XXX In this case, not specify either ledger does not mean ledger current. It means any ledger.
Json::Value RPCHandler::doTransactionEntry (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
Ledger::pointer lpLedger;
Json::Value jvResult = RPC::lookupLedger (params, lpLedger, *mNetOps);
if (!lpLedger)
return jvResult;
if (!params.isMember ("tx_hash"))
{
jvResult["error"] = "fieldNotFoundTransaction";
}
else if (!params.isMember ("ledger_hash") && !params.isMember ("ledger_index"))
{
// We don't work on ledger current.
jvResult["error"] = "notYetImplemented"; // XXX We don't support any transaction yet.
}
else
{
uint256 uTransID;
// XXX Relying on trusted WSS client. Would be better to have a strict routine, returning success or failure.
uTransID.SetHex (params["tx_hash"].asString ());
if (!lpLedger)
{
jvResult["error"] = "ledgerNotFound";
}
else
{
Transaction::pointer tpTrans;
TransactionMetaSet::pointer tmTrans;
if (!lpLedger->getTransaction (uTransID, tpTrans, tmTrans))
{
jvResult["error"] = "transactionNotFound";
}
else
{
jvResult["tx_json"] = tpTrans->getJson (0);
if (tmTrans)
jvResult["metadata"] = tmTrans->getJson (0);
// 'accounts'
// 'engine_...'
// 'ledger_...'
}
}
}
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,94 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// transaction: <hex>
// }
Json::Value RPCHandler::doTx (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
if (!params.isMember (jss::transaction))
return rpcError (rpcINVALID_PARAMS);
bool binary = params.isMember (jss::binary) && params[jss::binary].asBool ();
std::string strTransaction = params[jss::transaction].asString ();
if (Transaction::isHexTxID (strTransaction))
{
// transaction by ID
uint256 txid (strTransaction);
Transaction::pointer txn = getApp().getMasterTransaction ().fetch (txid, true);
if (!txn)
return rpcError (rpcTXN_NOT_FOUND);
#ifdef READY_FOR_NEW_TX_FORMAT
Json::Value ret;
ret[jss::transaction] = txn->getJson (0, binary);
#else
Json::Value ret = txn->getJson (0, binary);
#endif
if (txn->getLedger () != 0)
{
Ledger::pointer lgr = mNetOps->getLedgerBySeq (txn->getLedger ());
if (lgr)
{
bool okay = false;
if (binary)
{
std::string meta;
if (lgr->getMetaHex (txid, meta))
{
ret[jss::meta] = meta;
okay = true;
}
}
else
{
TransactionMetaSet::pointer set;
if (lgr->getTransactionMeta (txid, set))
{
okay = true;
ret[jss::meta] = set->getJson (0);
}
}
if (okay)
ret[jss::validated] = mNetOps->isValidated (lgr);
}
}
return ret;
}
return rpcError (rpcNOT_IMPL);
}
} // ripple

View File

@@ -0,0 +1,65 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// start: <index>
// }
Json::Value RPCHandler::doTxHistory (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
loadType = Resource::feeMediumBurdenRPC;
if (!params.isMember ("start"))
return rpcError (rpcINVALID_PARAMS);
unsigned int startIndex = params["start"].asUInt ();
if ((startIndex > 10000) && (mRole != Config::ADMIN))
return rpcError (rpcNO_PERMISSION);
Json::Value obj;
Json::Value txs;
obj["index"] = startIndex;
std::string sql =
boost::str (boost::format ("SELECT * FROM Transactions ORDER BY LedgerSeq desc LIMIT %u,20")
% startIndex);
{
Database* db = getApp().getTxnDB ()->getDB ();
DeprecatedScopedLock sl (getApp().getTxnDB ()->getDBLock ());
SQL_FOREACH (db, sql)
{
Transaction::pointer trans = Transaction::transactionFromSQL (db, false);
if (trans) txs.append (trans->getJson (0));
}
}
obj["txs"] = txs;
return obj;
}
} // ripple

View File

@@ -0,0 +1,48 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// node: <domain>|<node_public>,
// comment: <comment> // optional
// }
Json::Value RPCHandler::doUnlAdd (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
std::string strNode = params.isMember ("node") ? params["node"].asString () : "";
std::string strComment = params.isMember ("comment") ? params["comment"].asString () : "";
RippleAddress raNodePublic;
if (raNodePublic.setNodePublic (strNode))
{
getApp().getUNL ().nodeAddPublic (raNodePublic, UniqueNodeList::vsManual, strComment);
return "adding node by public key";
}
else
{
getApp().getUNL ().nodeAddDomain (strNode, UniqueNodeList::vsManual, strComment);
return "adding node by domain";
}
}
} // ripple

View File

@@ -0,0 +1,49 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// node: <domain>|<public_key>
// }
Json::Value RPCHandler::doUnlDelete (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
if (!params.isMember ("node"))
return rpcError (rpcINVALID_PARAMS);
std::string strNode = params["node"].asString ();
RippleAddress raNodePublic;
if (raNodePublic.setNodePublic (strNode))
{
getApp().getUNL ().nodeRemovePublic (raNodePublic);
return "removing node by public key";
}
else
{
getApp().getUNL ().nodeRemoveDomain (strNode);
return "removing node by domain";
}
}
} // ripple

View File

@@ -0,0 +1,32 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doUnlList (Json::Value, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
Json::Value obj (Json::objectValue);
obj["unl"] = getApp().getUNL ().getUnlJson ();
return obj;
}
} // ripple

View File

@@ -0,0 +1,34 @@
//------------------------------------------------------------------------------
/*
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 {
// Populate the UNL from a local validators.txt file.
Json::Value RPCHandler::doUnlLoad (Json::Value, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
if (getConfig ().VALIDATORS_FILE.empty () || !getApp().getUNL ().nodeLoad (getConfig ().VALIDATORS_FILE))
{
return rpcError (rpcLOAD_FAILED);
}
return "loading";
}
} // ripple

View File

@@ -0,0 +1,31 @@
//------------------------------------------------------------------------------
/*
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 {
// Populate the UNL from ripple.com's validators.txt file.
Json::Value RPCHandler::doUnlNetwork (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
getApp().getUNL ().nodeNetwork ();
return "fetching";
}
} // ripple

View File

@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
/*
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 {
Json::Value RPCHandler::doUnlReset (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
getApp().getUNL ().nodeReset ();
return "removing nodes";
}
} // ripple

View File

@@ -0,0 +1,31 @@
//------------------------------------------------------------------------------
/*
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 {
// unl_score
Json::Value RPCHandler::doUnlScore (Json::Value, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
getApp().getUNL ().nodeScore ();
return "scoring requested";
}
} // ripple

View File

@@ -0,0 +1,210 @@
//------------------------------------------------------------------------------
/*
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 {
// FIXME: This leaks RPCSub objects for JSON-RPC. Shouldn't matter for anyone sane.
Json::Value RPCHandler::doUnsubscribe (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
InfoSub::pointer ispSub;
Json::Value jvResult (Json::objectValue);
if (!mInfoSub && !params.isMember ("url"))
{
// Must be a JSON-RPC call.
return rpcError (rpcINVALID_PARAMS);
}
if (params.isMember ("url"))
{
if (mRole != Config::ADMIN)
return rpcError (rpcNO_PERMISSION);
std::string strUrl = params["url"].asString ();
ispSub = mNetOps->findRpcSub (strUrl);
if (!ispSub)
return jvResult;
}
else
{
ispSub = mInfoSub;
}
if (params.isMember ("streams"))
{
for (Json::Value::iterator it = params["streams"].begin (); it != params["streams"].end (); it++)
{
if ((*it).isString ())
{
std::string streamName = (*it).asString ();
if (streamName == "server")
{
mNetOps->unsubServer (ispSub->getSeq ());
}
else if (streamName == "ledger")
{
mNetOps->unsubLedger (ispSub->getSeq ());
}
else if (streamName == "transactions")
{
mNetOps->unsubTransactions (ispSub->getSeq ());
}
else if (streamName == "transactions_proposed"
|| streamName == "rt_transactions") // DEPRECATED
{
mNetOps->unsubRTTransactions (ispSub->getSeq ());
}
else
{
jvResult["error"] = str (boost::format ("Unknown stream: %s") % streamName);
}
}
else
{
jvResult["error"] = "malformedSteam";
}
}
}
if (params.isMember ("accounts_proposed") || params.isMember ("rt_accounts"))
{
boost::unordered_set<RippleAddress> usnaAccoundIds = RPC::parseAccountIds (
params.isMember ("accounts_proposed")
? params["accounts_proposed"]
: params["rt_accounts"]); // DEPRECATED
if (usnaAccoundIds.empty ())
{
jvResult["error"] = "malformedAccount";
}
else
{
mNetOps->unsubAccount (ispSub->getSeq (), usnaAccoundIds, true);
}
}
if (params.isMember ("accounts"))
{
boost::unordered_set<RippleAddress> usnaAccoundIds = RPC::parseAccountIds (params["accounts"]);
if (usnaAccoundIds.empty ())
{
jvResult["error"] = "malformedAccount";
}
else
{
mNetOps->unsubAccount (ispSub->getSeq (), usnaAccoundIds, false);
}
}
if (!params.isMember ("books"))
{
nothing ();
}
else if (!params["books"].isArray ())
{
return rpcError (rpcINVALID_PARAMS);
}
else
{
for (Json::Value::iterator it = params["books"].begin (); it != params["books"].end (); it++)
{
Json::Value& jvSubRequest = *it;
if (!jvSubRequest.isObject ()
|| !jvSubRequest.isMember ("taker_pays")
|| !jvSubRequest.isMember ("taker_gets")
|| !jvSubRequest["taker_pays"].isObject ()
|| !jvSubRequest["taker_gets"].isObject ())
return rpcError (rpcINVALID_PARAMS);
uint160 pay_currency;
uint160 pay_issuer;
uint160 get_currency;
uint160 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_gets = jvSubRequest["taker_gets"];
// Parse mandatory currency.
if (!taker_pays.isMember ("currency")
|| !STAmount::currencyFromString (pay_currency, taker_pays["currency"].asString ()))
{
WriteLog (lsINFO, RPCHandler) << "Bad taker_pays currency.";
return rpcError (rpcSRC_CUR_MALFORMED);
}
// Parse optional issuer.
else if (((taker_pays.isMember ("issuer"))
&& (!taker_pays["issuer"].isString ()
|| !STAmount::issuerFromString (pay_issuer, taker_pays["issuer"].asString ())))
// Don't allow illegal issuers.
|| (!pay_currency != !pay_issuer)
|| ACCOUNT_ONE == pay_issuer)
{
WriteLog (lsINFO, RPCHandler) << "Bad taker_pays issuer.";
return rpcError (rpcSRC_ISR_MALFORMED);
}
// Parse mandatory currency.
if (!taker_gets.isMember ("currency")
|| !STAmount::currencyFromString (get_currency, taker_gets["currency"].asString ()))
{
WriteLog (lsINFO, RPCHandler) << "Bad taker_pays currency.";
return rpcError (rpcSRC_CUR_MALFORMED);
}
// Parse optional issuer.
else if (((taker_gets.isMember ("issuer"))
&& (!taker_gets["issuer"].isString ()
|| !STAmount::issuerFromString (get_issuer, taker_gets["issuer"].asString ())))
// Don't allow illegal issuers.
|| (!get_currency != !get_issuer)
|| ACCOUNT_ONE == get_issuer)
{
WriteLog (lsINFO, RPCHandler) << "Bad taker_gets issuer.";
return rpcError (rpcDST_ISR_MALFORMED);
}
if (pay_currency == get_currency
&& pay_issuer == get_issuer)
{
WriteLog (lsINFO, RPCHandler) << "taker_gets same as taker_pays.";
return rpcError (rpcBAD_MARKET);
}
mNetOps->unsubBook (ispSub->getSeq (), pay_currency, get_currency, pay_issuer, get_issuer);
if (bBoth) mNetOps->unsubBook (ispSub->getSeq (), get_currency, pay_currency, get_issuer, pay_issuer);
}
}
return jvResult;
}
} // ripple

View File

@@ -0,0 +1,51 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// secret: <string> // optional
// }
//
// This command requires Config::ADMIN access because it makes no sense to ask an untrusted server for this.
Json::Value RPCHandler::doValidationCreate (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
RippleAddress raSeed;
Json::Value obj (Json::objectValue);
if (!params.isMember ("secret"))
{
WriteLog (lsDEBUG, RPCHandler) << "Creating random validation seed.";
raSeed.setSeedRandom (); // Get a random seed.
}
else if (!raSeed.setSeedGeneric (params["secret"].asString ()))
{
return rpcError (rpcBAD_SEED);
}
obj["validation_public_key"] = RippleAddress::createNodePublic (raSeed).humanNodePublic ();
obj["validation_seed"] = raSeed.humanSeed ();
obj["validation_key"] = raSeed.humanSeed1751 ();
return obj;
}
} // ripple

View File

@@ -0,0 +1,58 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// secret: <string>
// }
Json::Value RPCHandler::doValidationSeed (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
Json::Value obj (Json::objectValue);
if (!params.isMember ("secret"))
{
Log::out() << "Unset validation seed.";
getConfig ().VALIDATION_SEED.clear ();
getConfig ().VALIDATION_PUB.clear ();
getConfig ().VALIDATION_PRIV.clear ();
}
else if (!getConfig ().VALIDATION_SEED.setSeedGeneric (params["secret"].asString ()))
{
getConfig ().VALIDATION_PUB.clear ();
getConfig ().VALIDATION_PRIV.clear ();
return rpcError (rpcBAD_SEED);
}
else
{
getConfig ().VALIDATION_PUB = RippleAddress::createNodePublic (getConfig ().VALIDATION_SEED);
getConfig ().VALIDATION_PRIV = RippleAddress::createNodePrivate (getConfig ().VALIDATION_SEED);
obj["validation_public_key"] = getConfig ().VALIDATION_PUB.humanNodePublic ();
obj["validation_seed"] = getConfig ().VALIDATION_SEED.humanSeed ();
obj["validation_key"] = getConfig ().VALIDATION_SEED.humanSeed1751 ();
}
return obj;
}
} // ripple

View File

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// seed: <string>
// ledger_hash : <ledger>
// ledger_index : <ledger_index>
// }
Json::Value RPCHandler::doWalletAccounts (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
Ledger::pointer lpLedger;
Json::Value jvResult = RPC::lookupLedger (params, lpLedger, *mNetOps);
if (!lpLedger)
return jvResult;
RippleAddress naSeed;
if (!params.isMember ("seed") || !naSeed.setSeedGeneric (params["seed"].asString ()))
{
return rpcError (rpcBAD_SEED);
}
// Try the seed as a master seed.
RippleAddress naMasterGenerator = RippleAddress::createGeneratorPublic (naSeed);
Json::Value jsonAccounts = RPC::accounts (lpLedger, naMasterGenerator, *mNetOps);
if (jsonAccounts.empty ())
{
// No account via seed as master, try seed a regular.
Json::Value ret = RPC::getMasterGenerator (lpLedger, naSeed, naMasterGenerator, *mNetOps);
if (!ret.empty ())
return ret;
ret["accounts"] = RPC::accounts (lpLedger, naMasterGenerator, *mNetOps);
return ret;
}
else
{
// Had accounts via seed as master, return them.
Json::Value ret (Json::objectValue);
ret["accounts"] = jsonAccounts;
return ret;
}
}
} // ripple

View File

@@ -0,0 +1,56 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// passphrase: <string>
// }
Json::Value RPCHandler::doWalletPropose (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
masterLockHolder.unlock ();
RippleAddress naSeed;
RippleAddress naAccount;
if (!params.isMember ("passphrase"))
naSeed.setSeedRandom ();
else if (!naSeed.setSeedGeneric (params["passphrase"].asString ()))
return rpcError(rpcBAD_SEED);
RippleAddress naGenerator = RippleAddress::createGeneratorPublic (naSeed);
naAccount.setAccountPublic (naGenerator, 0);
Json::Value obj (Json::objectValue);
obj["master_seed"] = naSeed.humanSeed ();
obj["master_seed_hex"] = to_string (naSeed.getSeed ());
obj["master_key"] = naSeed.humanSeed1751();
obj["account_id"] = naAccount.humanAccountID ();
obj["public_key"] = naAccount.humanAccountPublic();
auto acct = naAccount.getAccountPublic();
obj["public_key_hex"] = strHex(acct.begin(), acct.size());
return obj;
}
} // ripple

View File

@@ -0,0 +1,56 @@
//------------------------------------------------------------------------------
/*
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 {
// {
// secret: <string>
// }
Json::Value RPCHandler::doWalletSeed (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
RippleAddress raSeed;
bool bSecret = params.isMember ("secret");
if (bSecret && !raSeed.setSeedGeneric (params["secret"].asString ()))
{
return rpcError (rpcBAD_SEED);
}
else
{
RippleAddress raAccount;
if (!bSecret)
{
raSeed.setSeedRandom ();
}
RippleAddress raGenerator = RippleAddress::createGeneratorPublic (raSeed);
raAccount.setAccountPublic (raGenerator, 0);
Json::Value obj (Json::objectValue);
obj["seed"] = raSeed.humanSeed ();
obj["key"] = raSeed.humanSeed1751 ();
obj["deprecated"] = "Use wallet_propose instead";
return obj;
}
}
} // ripple

View File

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

View File

@@ -0,0 +1,38 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#ifndef RIPPLE_RPC_ACCOUNTFROMSTRING_H_INCLUDED
#define RIPPLE_RPC_ACCOUNTFROMSTRING_H_INCLUDED
namespace ripple {
namespace RPC {
Json::Value accountFromString (
Ledger::ref lrLedger,
RippleAddress& naAccount,
bool& bIndex,
const std::string& strIdent,
const int iIndex,
const bool bStrict,
NetworkOPs& netOps);
} // RPC
} // ripple
#endif

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
/*
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/impl/Accounts.h>
namespace ripple {
namespace RPC {
Json::Value accounts (
Ledger::ref lrLedger,
const RippleAddress& naMasterGenerator,
NetworkOPs& netOps)
{
Json::Value jsonAccounts (Json::arrayValue);
// YYY Don't want to leak to thin server that these accounts are related.
// YYY Would be best to alternate requests to servers and to cache results.
unsigned int uIndex = 0;
do
{
RippleAddress naAccount;
naAccount.setAccountPublic (naMasterGenerator, uIndex++);
AccountState::pointer as = netOps.getAccountState (lrLedger, naAccount);
if (as)
{
Json::Value jsonAccount (Json::objectValue);
as->addJson (jsonAccount);
jsonAccounts.append (jsonAccount);
}
else
{
uIndex = 0;
}
}
while (uIndex);
return jsonAccounts;
}
} // RPC
} // ripple

View File

@@ -0,0 +1,34 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 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.
*/
//==============================================================================
#ifndef RIPPLE_RPC_ACCOUNTS_H_INCLUDED
#define RIPPLE_RPC_ACCOUNTS_H_INCLUDED
namespace ripple {
namespace RPC {
Json::Value accounts (
Ledger::ref lrLedger,
const RippleAddress& naMasterGenerator,
NetworkOPs& netOps);
} // RPC
} // ripple
#endif

View File

@@ -0,0 +1,125 @@
//------------------------------------------------------------------------------
/*
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/impl/Authorize.h>
namespace ripple {
namespace RPC {
// Given a seed and a source account get the regular public and private key for authorizing transactions.
// - Make sure the source account can pay.
// --> naRegularSeed : To find the generator
// --> naSrcAccountID : Account we want the public and private regular keys to.
// <-- naAccountPublic : Regular public key for naSrcAccountID
// <-- naAccountPrivate : Regular private key for naSrcAccountID
// <-- saSrcBalance: Balance minus fee.
// --> naVerifyGenerator : If provided, the found master public generator must match.
// XXX Be more lenient, allow use of master generator on claimed accounts.
Json::Value authorize (Ledger::ref lrLedger,
const RippleAddress& naRegularSeed, const RippleAddress& naSrcAccountID,
RippleAddress& naAccountPublic, RippleAddress& naAccountPrivate,
STAmount& saSrcBalance, const STAmount& saFee, AccountState::pointer& asSrc,
const RippleAddress& naVerifyGenerator, NetworkOPs& netOps)
{
// Source/paying account must exist.
asSrc = netOps.getAccountState (lrLedger, naSrcAccountID);
if (!asSrc)
{
return rpcError (rpcSRC_ACT_NOT_FOUND);
}
RippleAddress naMasterGenerator;
if (asSrc->haveAuthorizedKey ())
{
Json::Value obj = getMasterGenerator (lrLedger, naRegularSeed, naMasterGenerator, netOps);
if (!obj.empty ())
return obj;
}
else
{
// Try the seed as a master seed.
naMasterGenerator = RippleAddress::createGeneratorPublic (naRegularSeed);
}
// If naVerifyGenerator is provided, make sure it is the master generator.
if (naVerifyGenerator.isValid () && naMasterGenerator != naVerifyGenerator)
{
return rpcError (rpcWRONG_SEED);
}
// Find the index of the account from the master generator, so we can generate the public and private keys.
RippleAddress naMasterAccountPublic;
unsigned int iIndex = 0;
bool bFound = false;
// Don't look at ledger entries to determine if the account exists. Don't want to leak to thin server that these accounts are
// related.
while (!bFound && iIndex != getConfig ().ACCOUNT_PROBE_MAX)
{
naMasterAccountPublic.setAccountPublic (naMasterGenerator, iIndex);
WriteLog (lsDEBUG, RPCHandler) << "authorize: " << iIndex << " : " << naMasterAccountPublic.humanAccountID () << " : " << naSrcAccountID.humanAccountID ();
bFound = naSrcAccountID.getAccountID () == naMasterAccountPublic.getAccountID ();
if (!bFound)
++iIndex;
}
if (!bFound)
{
return rpcError (rpcACT_NOT_FOUND);
}
// Use the regular generator to determine the associated public and private keys.
RippleAddress naGenerator = RippleAddress::createGeneratorPublic (naRegularSeed);
naAccountPublic.setAccountPublic (naGenerator, iIndex);
naAccountPrivate.setAccountPrivate (naGenerator, naRegularSeed, iIndex);
if (asSrc->haveAuthorizedKey () && (asSrc->getAuthorizedKey ().getAccountID () != naAccountPublic.getAccountID ()))
{
// Log::out() << "iIndex: " << iIndex;
// Log::out() << "sfAuthorizedKey: " << strHex(asSrc->getAuthorizedKey().getAccountID());
// Log::out() << "naAccountPublic: " << strHex(naAccountPublic.getAccountID());
return rpcError (rpcPASSWD_CHANGED);
}
saSrcBalance = asSrc->getBalance ();
if (saSrcBalance < saFee)
{
WriteLog (lsINFO, RPCHandler) << "authorize: Insufficient funds for fees: fee=" << saFee.getText () << " balance=" << saSrcBalance.getText ();
return rpcError (rpcINSUF_FUNDS);
}
else
{
saSrcBalance -= saFee;
}
return Json::Value ();
}
} // RPC
} // ripple

View File

@@ -0,0 +1,41 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#ifndef RIPPLE_RPC_AUTHORIZE_H_INCLUDED
#define RIPPLE_RPC_AUTHORIZE_H_INCLUDED
namespace ripple {
namespace RPC {
Json::Value authorize (
Ledger::ref lrLedger,
const RippleAddress& naRegularSeed,
const RippleAddress& naSrcAccountID,
RippleAddress& naAccountPublic,
RippleAddress& naAccountPrivate,
STAmount& saSrcBalance,
const STAmount& saFee,
AccountState::pointer& asSrc,
const RippleAddress& naVerifyGenerator,
NetworkOPs& netOps);
} // RPC
} // ripple
#endif

View File

@@ -0,0 +1,35 @@
//------------------------------------------------------------------------------
/*
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_RPC_COMMAND_H_INCLUDED
#define RIPPLE_RPC_COMMAND_H_INCLUDED
namespace ripple {
namespace RPC {
/** Base class common to all RPC commands. */
class Command
{
public:
};
}
}
#endif

View File

@@ -0,0 +1,51 @@
//------------------------------------------------------------------------------
/*
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_RPC_PRINT_H_INCLUDED
#define RIPPLE_RPC_PRINT_H_INCLUDED
namespace ripple {
namespace RPC {
class DoPrint
{
public:
void operator() (Request& req)
{
JsonPropertyStream stream;
if (req.params.isObject() &&
req.params["params"].isArray() &&
req.params["params"][0u].isString ())
{
req.app.write (stream, req.params["params"][0u].asString());
}
else
{
req.app.write (stream);
}
req.result = stream.top();
}
};
}
}
#endif

View File

@@ -0,0 +1,189 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#include <unordered_map>
#include <utility>
#include <ripple/module/rpc/api/ErrorCodes.h>
namespace std {
template <>
struct hash <ripple::error_code_i>
{
std::size_t operator() (ripple::error_code_i value) const
{
return value;
}
};
}
namespace ripple {
namespace RPC {
namespace detail {
class ErrorCategory
{
public:
typedef ripple::unordered_map <error_code_i, ErrorInfo> Map;
ErrorCategory ()
: m_unknown (rpcUNKNOWN, "unknown", "An unknown error code.")
{
add (rpcACT_BITCOIN, "actBitcoin", "Account is bitcoin address.");
add (rpcACT_EXISTS, "actExists", "Account already exists.");
add (rpcACT_MALFORMED, "actMalformed", "Account malformed.");
add (rpcACT_NOT_FOUND, "actNotFound", "Account not found.");
add (rpcBAD_BLOB, "badBlob", "Blob must be a non-empty hex string.");
add (rpcBAD_FEATURE, "badFeature", "Feature unknown or invalid.");
add (rpcBAD_ISSUER, "badIssuer", "Issuer account malformed.");
add (rpcBAD_MARKET, "badMarket", "No such market.");
add (rpcBAD_SECRET, "badSecret", "Secret does not match account.");
add (rpcBAD_SEED, "badSeed", "Disallowed seed.");
add (rpcBAD_SYNTAX, "badSyntax", "Syntax error.");
add (rpcCOMMAND_MISSING, "commandMissing", "Missing command entry.");
add (rpcDST_ACT_MALFORMED, "dstActMalformed", "Destination account is malformed.");
add (rpcDST_ACT_MISSING, "dstActMissing", "Destination account does not exist.");
add (rpcDST_AMT_MALFORMED, "dstAmtMalformed", "Destination amount/currency/issuer is malformed.");
add (rpcDST_ISR_MALFORMED, "dstIsrMalformed", "Destination issuer is malformed.");
add (rpcFAIL_GEN_DECRYPT, "failGenDecrypt", "Failed to decrypt generator.");
add (rpcFORBIDDEN, "forbidden", "Bad credentials.");
add (rpcGETS_ACT_MALFORMED, "getsActMalformed", "Gets account malformed.");
add (rpcGETS_AMT_MALFORMED, "getsAmtMalformed", "Gets amount malformed.");
add (rpcHIGH_FEE, "highFee", "Current transaction fee exceeds your limit.");
add (rpcHOST_IP_MALFORMED, "hostIpMalformed", "Host IP is malformed.");
add (rpcINSUF_FUNDS, "insufFunds", "Insufficient funds.");
add (rpcINTERNAL, "internal", "Internal error.");
add (rpcINVALID_PARAMS, "invalidParams", "Invalid parameters.");
add (rpcJSON_RPC, "json_rpc", "JSON-RPC transport error.");
add (rpcLGR_IDXS_INVALID, "lgrIdxsInvalid", "Ledger indexes invalid.");
add (rpcLGR_IDX_MALFORMED, "lgrIdxMalformed", "Ledger index malformed.");
add (rpcLGR_NOT_FOUND, "lgrNotFound", "Ledger not found.");
add (rpcMASTER_DISABLED, "masterDisabled", "Master key is disabled.");
add (rpcNICKNAME_MALFORMED, "nicknameMalformed", "Nickname is malformed.");
add (rpcNICKNAME_MISSING, "nicknameMissing", "Nickname does not exist.");
add (rpcNICKNAME_PERM, "nicknamePerm", "Account does not control nickname.");
add (rpcNOT_IMPL, "notImpl", "Not implemented.");
add (rpcNO_ACCOUNT, "noAccount", "No such account.");
add (rpcNO_CLOSED, "noClosed", "Closed ledger is unavailable.");
add (rpcNO_CURRENT, "noCurrent", "Current ledger is unavailable.");
add (rpcNO_EVENTS, "noEvents", "Current transport does not support events.");
add (rpcNO_GEN_DECRYPT, "noGenDecrypt", "Password failed to decrypt master public generator.");
add (rpcNO_NETWORK, "noNetwork", "Not synced to Ripple network.");
add (rpcNO_PATH, "noPath", "Unable to find a ripple path.");
add (rpcNO_PERMISSION, "noPermission", "You don't have permission for this command.");
add (rpcNO_PF_REQUEST, "noPathRequest", "No pathfinding request in progress.");
add (rpcNOT_STANDALONE, "notStandAlone", "Operation valid in debug mode only.");
add (rpcNOT_SUPPORTED, "notSupported", "Operation not supported.");
add (rpcPASSWD_CHANGED, "passwdChanged", "Wrong key, password changed.");
add (rpcPAYS_ACT_MALFORMED, "paysActMalformed", "Pays account malformed.");
add (rpcPAYS_AMT_MALFORMED, "paysAmtMalformed", "Pays amount malformed.");
add (rpcPORT_MALFORMED, "portMalformed", "Port is malformed.");
add (rpcPUBLIC_MALFORMED, "publicMalformed", "Public key is malformed.");
add (rpcQUALITY_MALFORMED, "qualityMalformed", "Quality malformed.");
add (rpcSRC_ACT_MALFORMED, "srcActMalformed", "Source account is malformed.");
add (rpcSRC_ACT_MISSING, "srcActMissing", "Source account not provided.");
add (rpcSRC_ACT_NOT_FOUND, "srcActNotFound", "Source account not found.");
add (rpcSRC_AMT_MALFORMED, "srcAmtMalformed", "Source amount/currency/issuer is malformed.");
add (rpcSRC_CUR_MALFORMED, "srcCurMalformed", "Source currency is malformed.");
add (rpcSRC_ISR_MALFORMED, "srcIsrMalformed", "Source issuer is malformed.");
add (rpcSRC_UNCLAIMED, "srcUnclaimed", "Source account is not claimed.");
add (rpcTXN_NOT_FOUND, "txnNotFound", "Transaction not found.");
add (rpcUNKNOWN_COMMAND, "unknownCmd", "Unknown method.");
add (rpcWRONG_SEED, "wrongSeed", "The regular key does not point as the master key.");
add (rpcTOO_BUSY, "tooBusy", "The server is too busy to help you now.");
add (rpcSLOW_DOWN, "slowDown", "You are placing too much load on the server.");
add (rpcATX_DEPRECATED, "deprecated", "Use the new API or specify a ledger range.");
}
ErrorInfo const& get (error_code_i code) const
{
Map::const_iterator const iter (m_map.find (code));
if (iter != m_map.end())
return iter->second;
return m_unknown;
}
private:
void add (error_code_i code, std::string const& token,
std::string const& message)
{
std::pair <Map::iterator, bool> result (
m_map.emplace (std::piecewise_construct,
std::forward_as_tuple (code), std::forward_as_tuple (
code, token, message)));
if (! result.second)
throw std::invalid_argument ("duplicate error code");
}
private:
Map m_map;
ErrorInfo m_unknown;
};
}
//------------------------------------------------------------------------------
ErrorInfo const& get_error_info (error_code_i code)
{
static detail::ErrorCategory category;
return category.get (code);
}
void inject_error (error_code_i code, Json::Value& json)
{
ErrorInfo const& info (get_error_info (code));
json ["error"] = info.token;
json ["error_code"] = info.code;
json ["error_message"] = info.message;
}
void inject_error (error_code_i code, std::string const& message, Json::Value& json)
{
ErrorInfo const& info (get_error_info (code));
json ["error"] = info.token;
json ["error_code"] = info.code;
json ["error_message"] = message;
}
Json::Value make_error (error_code_i code)
{
Json::Value json;
inject_error (code, json);
return json;
}
Json::Value make_error (error_code_i code, std::string const& message)
{
Json::Value json;
inject_error (code, message, json);
return json;
}
bool contains_error (Json::Value const& json)
{
if (json.isObject() && json.isMember ("error"))
return true;
return false;
}
}
}

View File

@@ -0,0 +1,61 @@
//------------------------------------------------------------------------------
/*
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/impl/GetMasterGenerator.h>
namespace ripple {
namespace RPC {
// Look up the master public generator for a regular seed so we may index source accounts ids.
// --> naRegularSeed
// <-- naMasterGenerator
Json::Value getMasterGenerator (
Ledger::ref lrLedger, const RippleAddress& naRegularSeed,
RippleAddress& naMasterGenerator, NetworkOPs& netOps)
{
RippleAddress na0Public; // To find the generator's index.
RippleAddress na0Private; // To decrypt the master generator's cipher.
RippleAddress naGenerator = RippleAddress::createGeneratorPublic (naRegularSeed);
na0Public.setAccountPublic (naGenerator, 0);
na0Private.setAccountPrivate (naGenerator, naRegularSeed, 0);
SLE::pointer sleGen = netOps.getGenerator (lrLedger, na0Public.getAccountID ());
if (!sleGen)
{
// No account has been claimed or has had it password set for seed.
return rpcError (rpcNO_ACCOUNT);
}
Blob vucCipher = sleGen->getFieldVL (sfGenerator);
Blob vucMasterGenerator = na0Private.accountPrivateDecrypt (na0Public, vucCipher);
if (vucMasterGenerator.empty ())
{
return rpcError (rpcFAIL_GEN_DECRYPT);
}
naMasterGenerator.setGenerator (vucMasterGenerator);
return Json::Value (Json::objectValue);
}
} // RPC
} // ripple

View File

@@ -0,0 +1,35 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#ifndef RIPPLE_RPC_GETMASTERGENERATOR_H_INCLUDED
#define RIPPLE_RPC_GETMASTERGENERATOR_H_INCLUDED
namespace ripple {
namespace RPC {
Json::Value getMasterGenerator (
Ledger::ref lrLedger,
const RippleAddress& naRegularSeed,
RippleAddress& naMasterGenerator,
NetworkOPs& netOps);
} // RPC
} // ripple
#endif

View File

@@ -0,0 +1,91 @@
//------------------------------------------------------------------------------
/*
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/handlers/AccountCurrencies.cpp>
#include <ripple/module/rpc/handlers/AccountInfo.cpp>
#include <ripple/module/rpc/handlers/AccountLines.cpp>
#include <ripple/module/rpc/handlers/AccountOffers.cpp>
#include <ripple/module/rpc/handlers/AccountTx.cpp>
#include <ripple/module/rpc/handlers/AccountTxOld.cpp>
#include <ripple/module/rpc/handlers/AccountTxSwitch.cpp>
#include <ripple/module/rpc/handlers/BlackList.cpp>
#include <ripple/module/rpc/handlers/BookOffers.cpp>
#include <ripple/module/rpc/handlers/Connect.cpp>
#include <ripple/module/rpc/handlers/ConsensusInfo.cpp>
#include <ripple/module/rpc/handlers/Feature.cpp>
#include <ripple/module/rpc/handlers/FetchInfo.cpp>
#include <ripple/module/rpc/handlers/GetCounts.cpp>
#include <ripple/module/rpc/handlers/Ledger.cpp>
#include <ripple/module/rpc/handlers/LedgerAccept.cpp>
#include <ripple/module/rpc/handlers/LedgerCleaner.cpp>
#include <ripple/module/rpc/handlers/LedgerClosed.cpp>
#include <ripple/module/rpc/handlers/LedgerCurrent.cpp>
#include <ripple/module/rpc/handlers/LedgerData.cpp>
#include <ripple/module/rpc/handlers/LedgerEntry.cpp>
#include <ripple/module/rpc/handlers/LedgerHeader.cpp>
#include <ripple/module/rpc/handlers/LogLevel.cpp>
#include <ripple/module/rpc/handlers/LogRotate.cpp>
#include <ripple/module/rpc/handlers/NicknameInfo.cpp>
#include <ripple/module/rpc/handlers/OwnerInfo.cpp>
#include <ripple/module/rpc/handlers/PathFind.cpp>
#include <ripple/module/rpc/handlers/Peers.cpp>
#include <ripple/module/rpc/handlers/Ping.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/ProofSolve.cpp>
#include <ripple/module/rpc/handlers/ProofVerify.cpp>
#include <ripple/module/rpc/handlers/Random.cpp>
#include <ripple/module/rpc/handlers/RipplePathFind.cpp>
#include <ripple/module/rpc/handlers/SMS.cpp>
#include <ripple/module/rpc/handlers/ServerInfo.cpp>
#include <ripple/module/rpc/handlers/ServerState.cpp>
#include <ripple/module/rpc/handlers/Sign.cpp>
#include <ripple/module/rpc/handlers/Stop.cpp>
#include <ripple/module/rpc/handlers/Submit.cpp>
#include <ripple/module/rpc/handlers/Subscribe.cpp>
#include <ripple/module/rpc/handlers/TransactionEntry.cpp>
#include <ripple/module/rpc/handlers/Tx.cpp>
#include <ripple/module/rpc/handlers/TxHistory.cpp>
#include <ripple/module/rpc/handlers/UnlAdd.cpp>
#include <ripple/module/rpc/handlers/UnlDelete.cpp>
#include <ripple/module/rpc/handlers/UnlList.cpp>
#include <ripple/module/rpc/handlers/UnlLoad.cpp>
#include <ripple/module/rpc/handlers/UnlNetwork.cpp>
#include <ripple/module/rpc/handlers/UnlReset.cpp>
#include <ripple/module/rpc/handlers/UnlScore.cpp>
#include <ripple/module/rpc/handlers/Unsubscribe.cpp>
#include <ripple/module/rpc/handlers/ValidationCreate.cpp>
#include <ripple/module/rpc/handlers/ValidationSeed.cpp>
#include <ripple/module/rpc/handlers/WalletAccounts.cpp>
#include <ripple/module/rpc/handlers/WalletPropose.cpp>
#include <ripple/module/rpc/handlers/WalletSeed.cpp>
#include <ripple/module/rpc/impl/AccountFromString.cpp>
#include <ripple/module/rpc/impl/Accounts.cpp>
#include <ripple/module/rpc/impl/Authorize.cpp>
#include <ripple/module/rpc/impl/GetMasterGenerator.cpp>
#include <ripple/module/rpc/impl/LegacyPathFind.cpp>
#include <ripple/module/rpc/impl/LookupLedger.cpp>
#include <ripple/module/rpc/impl/ParseAccountIds.cpp>
#include <ripple/module/rpc/impl/TransactionSign.cpp>
#include <ripple/module/overlay/api/Overlay.h>
#include <tuple>

View File

@@ -0,0 +1,67 @@
//------------------------------------------------------------------------------
/*
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/impl/LegacyPathFind.h>
#include <ripple/module/rpc/api/Tuning.h>
namespace ripple {
namespace RPC {
LegacyPathFind::LegacyPathFind (bool isAdmin) : m_isOk (false)
{
if (isAdmin)
{
++inProgress;
m_isOk = true;
return;
}
auto& app = getApp();
auto const& jobCount = app.getJobQueue ().getJobCountGE (jtCLIENT);
if (jobCount > MAX_PATHFIND_JOB_COUNT || app.getFeeTrack().isLoadedLocal ())
return;
while (true)
{
int prevVal = inProgress.load();
if (prevVal >= MAX_PATHFINDS_IN_PROGRESS)
return;
if (inProgress.compare_exchange_strong (
prevVal,
prevVal + 1,
std::memory_order_release,
std::memory_order_relaxed))
{
m_isOk = true;
return;
}
}
}
LegacyPathFind::~LegacyPathFind ()
{
if (m_isOk)
--inProgress;
}
std::atomic <int> LegacyPathFind::inProgress (0);
} // RPC
} // ripple

View File

@@ -0,0 +1,46 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#ifndef RIPPLE_RPC_LEGACYPATHFIND_H_INCLUDED
#define RIPPLE_RPC_LEGACYPATHFIND_H_INCLUDED
namespace ripple {
namespace RPC {
class LegacyPathFind
{
public:
LegacyPathFind (bool isAdmin);
~LegacyPathFind ();
bool isOk () const
{
return m_isOk;
}
private:
static std::atomic <int> inProgress;
bool m_isOk;
};
} // RPC
} // ripple
#endif

View File

@@ -0,0 +1,219 @@
//------------------------------------------------------------------------------
/*
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/impl/LookupLedger.h>
namespace ripple {
namespace RPC {
static const int LEDGER_CURRENT = -1;
static const int LEDGER_CLOSED = -2;
static const int LEDGER_VALIDATED = -3;
// The previous version of the lookupLedger command would accept the
// "ledger_index" argument as a string and silently treat it as a request to
// return the current ledger which, while not strictly wrong, could cause a
// lot of confusion.
//
// The code now robustly validates the input and ensures that the only possible
// values for the "ledger_index" parameter are the index of a ledger passed as
// an integer or one of the strings "current", "closed" or "validated".
// Additionally, the code ensures that the value passed in "ledger_hash" is a
// string and a valid hash. Invalid values will return an appropriate error
// code.
//
// In the absence of the "ledger_hash" or "ledger_index" parameters, the code
// assumes that "ledger_index" has the value "current".
Json::Value lookupLedger (
Json::Value const& params,
Ledger::pointer& lpLedger,
NetworkOPs& netOps)
{
Json::Value jvResult;
Json::Value ledger_hash = params.get (jss::ledger_hash, Json::Value ("0"));
Json::Value ledger_index = params.get (jss::ledger_index, Json::Value ("current"));
// Support for DEPRECATED "ledger" - attempt to deduce our input
if (params.isMember (jss::ledger))
{
if (params[jss::ledger].asString ().size () > 12)
{
ledger_hash = params[jss::ledger];
ledger_index = Json::Value ("");
}
else if (params[jss::ledger].isNumeric ())
{
ledger_index = params[jss::ledger];
ledger_hash = Json::Value ("0");
}
else
{
ledger_index = params[jss::ledger];
ledger_hash = Json::Value ("0");
}
}
uint256 uLedger (0);
if (!ledger_hash.isString() || !uLedger.SetHex (ledger_hash.asString ()))
{
RPC::inject_error(rpcINVALID_PARAMS, "ledgerHashMalformed", jvResult);
return jvResult;
}
std::int32_t iLedgerIndex = LEDGER_CURRENT;
// We only try to parse a ledger index if we have not already
// determined that we have a ledger hash.
if (!uLedger)
{
if (ledger_index.isNumeric ())
iLedgerIndex = ledger_index.asInt ();
else
{
std::string strLedger = ledger_index.asString ();
if (strLedger == "current")
{
iLedgerIndex = LEDGER_CURRENT;
}
else if (strLedger == "closed")
{
iLedgerIndex = LEDGER_CLOSED;
}
else if (strLedger == "validated")
{
iLedgerIndex = LEDGER_VALIDATED;
}
else
{
RPC::inject_error(rpcINVALID_PARAMS, "ledgerIndexMalformed", jvResult);
return jvResult;
}
}
}
// The ledger was directly specified by hash.
if (uLedger.isNonZero ())
{
lpLedger = netOps.getLedgerByHash (uLedger);
if (!lpLedger)
{
RPC::inject_error(rpcLGR_NOT_FOUND, "ledgerNotFound", jvResult);
return jvResult;
}
iLedgerIndex = lpLedger->getLedgerSeq ();
}
int ledger_request = 0;
switch (iLedgerIndex)
{
case LEDGER_CURRENT:
lpLedger = netOps.getCurrentLedger ();
iLedgerIndex = lpLedger->getLedgerSeq ();
assert (lpLedger->isImmutable () && !lpLedger->isClosed ());
ledger_request = LEDGER_CURRENT;
break;
case LEDGER_CLOSED:
lpLedger = getApp().getLedgerMaster ().getClosedLedger ();
iLedgerIndex = lpLedger->getLedgerSeq ();
assert (lpLedger->isImmutable () && lpLedger->isClosed ());
ledger_request = LEDGER_CLOSED;
break;
case LEDGER_VALIDATED:
lpLedger = netOps.getValidatedLedger ();
iLedgerIndex = lpLedger->getLedgerSeq ();
assert (lpLedger->isImmutable () && lpLedger->isClosed ());
ledger_request = LEDGER_VALIDATED;
break;
}
if (iLedgerIndex <= 0)
{
RPC::inject_error(rpcINVALID_PARAMS, "ledgerIndexMalformed", jvResult);
return jvResult;
}
if (!lpLedger)
{
lpLedger = netOps.getLedgerBySeq (iLedgerIndex);
if (!lpLedger)
{
RPC::inject_error(rpcLGR_NOT_FOUND, "ledgerNotFound", jvResult);
return jvResult;
}
}
if (lpLedger->isClosed ())
{
if (uLedger.isNonZero ())
jvResult[jss::ledger_hash] = to_string (uLedger);
jvResult[jss::ledger_index] = iLedgerIndex;
}
else
{
jvResult[jss::ledger_current_index] = iLedgerIndex;
}
if (lpLedger->isValidated ())
jvResult[jss::validated] = true;
else
{
if (!lpLedger->isClosed ())
jvResult[jss::validated] = false;
else if (ledger_request == LEDGER_VALIDATED)
{
lpLedger->setValidated();
jvResult[jss::validated] = true;
}
else
{
try
{
// Use the skip list in the last validated ledger to see if lpLedger
// comes after the last validated ledger (and thus has been validated)
if (uLedger == getApp().getLedgerMaster ().walkHashBySeq (iLedgerIndex))
{
lpLedger->setValidated();
jvResult[jss::validated] = true;
}
else
{
jvResult[jss::validated] = false;
}
}
catch (SHAMapMissingNode const&)
{
jvResult[jss::validated] = false;
}
}
}
return jvResult;
}
} // RPC
} // ripple

View File

@@ -0,0 +1,34 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#ifndef RIPPLE_RPC_LOOKUPLEDGER_H_INCLUDED
#define RIPPLE_RPC_LOOKUPLEDGER_H_INCLUDED
namespace ripple {
namespace RPC {
Json::Value lookupLedger (
Json::Value const& jvRequest,
Ledger::pointer& lpLedger,
NetworkOPs& netOps);
} // RPC
} // ripple
#endif

View File

@@ -0,0 +1,74 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#include <beast/cxx14/memory.h>
#include <ripple/module/rpc/api/Manager.h>
#include <ripple/module/rpc/impl/DoPrint.h>
namespace ripple {
namespace RPC {
class ManagerImp : public Manager
{
public:
typedef ripple::unordered_map <std::string, handler_type> Map;
beast::Journal m_journal;
Map m_map;
ManagerImp (beast::Journal journal)
: m_journal (journal)
{
}
void add (std::string const& method, handler_type&& handler)
{
m_map.emplace (std::piecewise_construct, std::forward_as_tuple (method),
std::forward_as_tuple (std::move (handler)));
}
bool dispatch (Request& req)
{
Map::const_iterator const iter (m_map.find (req.method));
if (iter == m_map.end())
return false;
iter->second (req);
return true;
}
};
//------------------------------------------------------------------------------
Manager::~Manager ()
{
}
std::unique_ptr <Manager> make_Manager (beast::Journal journal)
{
std::unique_ptr <Manager> m (std::make_unique <ManagerImp> (journal));
m->add <DoPrint> ("print");
return m;
}
}
}

View File

@@ -0,0 +1,48 @@
//------------------------------------------------------------------------------
/*
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/impl/ParseAccountIds.h>
namespace ripple {
namespace RPC {
boost::unordered_set<RippleAddress> parseAccountIds (const Json::Value& jvArray)
{
boost::unordered_set<RippleAddress> usnaResult;
for (Json::Value::const_iterator it = jvArray.begin (); it != jvArray.end (); it++)
{
RippleAddress naString;
if (! (*it).isString () || !naString.setAccountID ((*it).asString ()))
{
usnaResult.clear ();
break;
}
else
{
(void) usnaResult.insert (naString);
}
}
return usnaResult;
}
} // RPC
} // ripple

View File

@@ -0,0 +1,31 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#ifndef RIPPLE_RPC_PARSEACCOUNTIDS_H_INCLUDED
#define RIPPLE_RPC_PARSEACCOUNTIDS_H_INCLUDED
namespace ripple {
namespace RPC {
boost::unordered_set <RippleAddress> parseAccountIds (const Json::Value& jvArray);
} // RPC
} // ripple
#endif

View File

@@ -0,0 +1,457 @@
//------------------------------------------------------------------------------
/*
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/impl/TransactionSign.h>
namespace ripple {
//------------------------------------------------------------------------------
namespace RPC {
/** Fill in the fee on behalf of the client.
This is called when the client does not explicitly specify the fee.
The client may also put a ceiling on the amount of the fee. This ceiling
is expressed as a multiplier based on the current ledger's fee schedule.
JSON fields
"Fee" The fee paid by the transaction. Omitted when the client
wants the fee filled in.
"fee_mult_max" A multiplier applied to the current ledger's transaction
fee that caps the maximum the fee server should auto fill.
If this optional field is not specified, then a default
multiplier is used.
@param tx The JSON corresponding to the transaction to fill in
@param ledger A ledger for retrieving the current fee schedule
@param result A JSON object for injecting error results, if any
@param admin `true` if this is called by an administrative endpoint.
*/
static void autofill_fee (Json::Value& request,
Ledger::pointer ledger, Json::Value& result, bool admin)
{
Json::Value& tx (request["tx_json"]);
if (tx.isMember ("Fee"))
return;
int mult = DEFAULT_AUTO_FILL_FEE_MULTIPLIER;
if (request.isMember ("fee_mult_max"))
{
if (request["fee_mult_max"].isNumeric ())
{
mult = request["fee_mult_max"].asInt();
}
else
{
RPC::inject_error (rpcHIGH_FEE, RPC::expected_field_message (
"fee_mult_max", "a number"), result);
return;
}
}
std::uint64_t const feeDefault = getConfig().FEE_DEFAULT;
// Administrative endpoints are exempt from local fees
std::uint64_t const fee = ledger->scaleFeeLoad (feeDefault, admin);
std::uint64_t const limit = mult * feeDefault;
if (fee > limit)
{
std::stringstream ss;
ss <<
"Fee of " << fee <<
" exceeds the requested tx limit of " << limit;
RPC::inject_error (rpcHIGH_FEE, ss.str(), result);
return;
}
tx ["Fee"] = static_cast<int>(fee);
}
static Json::Value signPayment(
Json::Value const& params,
Json::Value& tx_json,
RippleAddress const& raSrcAddressID,
Ledger::pointer lSnapshot,
int role)
{
RippleAddress dstAccountID;
if (!tx_json.isMember ("Amount"))
return RPC::missing_field_error ("tx_json.Amount");
STAmount amount;
if (!amount.bSetJson (tx_json ["Amount"]))
return RPC::invalid_field_error ("tx_json.Amount");
if (!tx_json.isMember ("Destination"))
return RPC::missing_field_error ("tx_json.Destination");
if (!dstAccountID.setAccountID (tx_json["Destination"].asString ()))
return RPC::invalid_field_error ("tx_json.Destination");
if (tx_json.isMember ("Paths") && params.isMember ("build_path"))
return RPC::make_error (rpcINVALID_PARAMS,
"Cannot specify both 'tx_json.Paths' and 'tx_json.build_path'");
if (!tx_json.isMember ("Paths")
&& tx_json.isMember ("Amount")
&& params.isMember ("build_path"))
{
// Need a ripple path.
STPathSet spsPaths;
uint160 uSrcCurrencyID;
uint160 uSrcIssuerID;
STAmount saSendMax;
if (tx_json.isMember ("SendMax"))
{
if (!saSendMax.bSetJson (tx_json ["SendMax"]))
return RPC::invalid_field_error ("tx_json.SendMax");
}
else
{
// If no SendMax, default to Amount with sender as issuer.
saSendMax = amount;
saSendMax.setIssuer (raSrcAddressID.getAccountID ());
}
if (saSendMax.isNative () && amount.isNative ())
return RPC::make_error (rpcINVALID_PARAMS,
"Cannot build XRP to XRP paths.");
{
LegacyPathFind lpf (role == Config::ADMIN);
if (!lpf.isOk ())
return rpcError (rpcTOO_BUSY);
bool bValid;
auto cache = boost::make_shared<RippleLineCache> (lSnapshot);
Pathfinder pf (cache, raSrcAddressID, dstAccountID,
saSendMax.getCurrency (), saSendMax.getIssuer (),
amount, bValid);
STPath extraPath;
if (!bValid || !pf.findPaths (getConfig ().PATH_SEARCH_OLD, 4, spsPaths, extraPath))
{
WriteLog (lsDEBUG, RPCHandler)
<< "transactionSign: build_path: No paths found.";
return rpcError (rpcNO_PATH);
}
WriteLog (lsDEBUG, RPCHandler)
<< "transactionSign: build_path: "
<< spsPaths.getJson (0);
if (!spsPaths.isEmpty ())
tx_json["Paths"] = spsPaths.getJson (0);
}
}
return Json::Value();
}
//------------------------------------------------------------------------------
// VFALCO TODO This function should take a reference to the params, modify it
// as needed, and then there should be a separate function to
// submit the tranaction
//
Json::Value transactionSign (
Json::Value params, bool bSubmit, bool bFailHard,
Application::ScopedLockType& mlh, NetworkOPs& netOps, int role)
{
Json::Value jvResult;
WriteLog (lsDEBUG, RPCHandler) << "transactionSign: " << params;
if (! params.isMember ("secret"))
return RPC::missing_field_error ("secret");
if (! params.isMember ("tx_json"))
return RPC::missing_field_error ("tx_json");
RippleAddress naSeed;
if (! naSeed.setSeedGeneric (params["secret"].asString ()))
return RPC::make_error (rpcBAD_SEED,
RPC::invalid_field_message ("secret"));
Json::Value& tx_json (params ["tx_json"]);
if (! tx_json.isObject ())
return RPC::object_field_error ("tx_json");
if (! tx_json.isMember ("TransactionType"))
return RPC::missing_field_error ("tx_json.TransactionType");
std::string const sType = tx_json ["TransactionType"].asString ();
if (! tx_json.isMember ("Account"))
return RPC::make_error (rpcSRC_ACT_MISSING,
RPC::missing_field_message ("tx_json.Account"));
RippleAddress raSrcAddressID;
if (! raSrcAddressID.setAccountID (tx_json["Account"].asString ()))
return RPC::make_error (rpcSRC_ACT_MALFORMED,
RPC::invalid_field_message ("tx_json.Account"));
bool const verify = !(params.isMember ("offline")
&& params["offline"].asBool ());
if (!tx_json.isMember ("Sequence") && !verify)
return RPC::missing_field_error ("tx_json.Sequence");
// Check for current ledger
if (verify && !getConfig ().RUN_STANDALONE &&
(getApp().getLedgerMaster().getValidatedLedgerAge() > 120))
return rpcError (rpcNO_CURRENT);
// Check for load
if (getApp().getFeeTrack().isLoadedCluster() && (role != Config::ADMIN))
return rpcError(rpcTOO_BUSY);
Ledger::pointer lSnapshot = netOps.getCurrentLedger ();
AccountState::pointer asSrc;
if (verify) {
asSrc = netOps.getAccountState (lSnapshot, raSrcAddressID);
if (!asSrc)
{
// If not offline and did not find account, error.
WriteLog (lsDEBUG, RPCHandler)
<< "transactionSign: Failed to find source account in current ledger: "
<< raSrcAddressID.humanAccountID ();
return rpcError (rpcSRC_ACT_NOT_FOUND);
}
}
autofill_fee (params, lSnapshot, jvResult, role == Config::ADMIN);
if (RPC::contains_error (jvResult))
return jvResult;
if ("Payment" == sType)
{
auto e = signPayment(params, tx_json, raSrcAddressID, lSnapshot, role);
if (contains_error(e))
return e;
}
if (!tx_json.isMember ("Fee")) {
auto const& transactionType = tx_json["TransactionType"].asString ();
if ("AccountSet" == transactionType
|| "OfferCreate" == transactionType
|| "OfferCancel" == transactionType
|| "TrustSet" == transactionType)
{
tx_json["Fee"] = (int) getConfig ().FEE_DEFAULT;
}
}
if (!tx_json.isMember ("Sequence"))
tx_json["Sequence"] = asSrc->getSeq ();
if (!tx_json.isMember ("Flags"))
tx_json["Flags"] = tfFullyCanonicalSig;
if (verify)
{
SLE::pointer sleAccountRoot = netOps.getSLEi (lSnapshot,
Ledger::getAccountRootIndex (raSrcAddressID.getAccountID ()));
if (!sleAccountRoot)
// XXX Ignore transactions for accounts not created.
return rpcError (rpcSRC_ACT_NOT_FOUND);
}
RippleAddress naSecret = RippleAddress::createSeedGeneric (
params["secret"].asString ());
RippleAddress naMasterGenerator = RippleAddress::createGeneratorPublic (
naSecret);
RippleAddress masterAccountPublic = RippleAddress::createAccountPublic (
naMasterGenerator, 0);
if (verify)
{
auto account = masterAccountPublic.getAccountID();
auto const& sle = asSrc->peekSLE();
WriteLog (lsWARNING, RPCHandler) <<
"verify: " << masterAccountPublic.humanAccountID () <<
" : " << raSrcAddressID.humanAccountID ();
if (raSrcAddressID.getAccountID () == account)
{
if (sle.isFlag(lsfDisableMaster))
return rpcError (rpcMASTER_DISABLED);
}
else if (!sle.isFieldPresent(sfRegularKey) ||
account != sle.getFieldAccount160 (sfRegularKey))
{
return rpcError (rpcBAD_SECRET);
}
}
STParsedJSON parsed ("tx_json", tx_json);
if (!parsed.object.get())
{
jvResult ["error"] = parsed.error ["error"];
jvResult ["error_code"] = parsed.error ["error_code"];
jvResult ["error_message"] = parsed.error ["error_message"];
return jvResult;
}
std::unique_ptr<STObject> sopTrans = std::move(parsed.object);
sopTrans->setFieldVL (sfSigningPubKey, masterAccountPublic.getAccountPublic ());
SerializedTransaction::pointer stpTrans;
try
{
stpTrans = boost::make_shared<SerializedTransaction> (*sopTrans);
}
catch (std::exception&)
{
return RPC::make_error (rpcINTERNAL,
"Exception occurred during transaction");
}
std::string reason;
if (!passesLocalChecks (*stpTrans, reason))
return RPC::make_error (rpcINVALID_PARAMS, reason);
if (params.isMember ("debug_signing"))
{
jvResult["tx_unsigned"] = strHex (
stpTrans->getSerializer ().peekData ());
jvResult["tx_signing_hash"] = to_string (stpTrans->getSigningHash ());
}
// FIXME: For performance, transactions should not be signed in this code path.
RippleAddress naAccountPrivate = RippleAddress::createAccountPrivate (
naMasterGenerator, naSecret, 0);
stpTrans->sign (naAccountPrivate);
Transaction::pointer tpTrans;
try
{
tpTrans = boost::make_shared<Transaction> (stpTrans, false);
}
catch (std::exception&)
{
return RPC::make_error (rpcINTERNAL,
"Exception occurred during transaction");
}
try
{
// FIXME: For performance, should use asynch interface
tpTrans = netOps.submitTransactionSync (tpTrans,
role == Config::ADMIN, true, bFailHard, bSubmit);
if (!tpTrans)
{
return RPC::make_error (rpcINTERNAL,
"Unable to sterilize transaction.");
}
}
catch (std::exception&)
{
return RPC::make_error (rpcINTERNAL,
"Exception occurred during transaction submission.");
}
try
{
jvResult["tx_json"] = tpTrans->getJson (0);
jvResult["tx_blob"] = strHex (
tpTrans->getSTransaction ()->getSerializer ().peekData ());
if (temUNCERTAIN != tpTrans->getResult ())
{
std::string sToken;
std::string sHuman;
transResultInfo (tpTrans->getResult (), sToken, sHuman);
jvResult["engine_result"] = sToken;
jvResult["engine_result_code"] = tpTrans->getResult ();
jvResult["engine_result_message"] = sHuman;
}
return jvResult;
}
catch (std::exception&)
{
return RPC::make_error (rpcINTERNAL,
"Exception occurred during JSON handling.");
}
}
class JSONRPC_test : public beast::unit_test::suite
{
public:
void testAutoFillFees ()
{
RippleAddress rootSeedMaster = RippleAddress::createSeedGeneric ("masterpassphrase");
RippleAddress rootGeneratorMaster = RippleAddress::createGeneratorPublic (rootSeedMaster);
RippleAddress rootAddress = RippleAddress::createAccountPublic (rootGeneratorMaster, 0);
std::uint64_t startAmount (100000);
Ledger::pointer ledger (boost::make_shared <Ledger> (
rootAddress, startAmount));
{
Json::Value req;
Json::Value result;
Json::Reader ().parse (
"{ \"fee_mult_max\" : 1, \"tx_json\" : { } } "
, req);
autofill_fee (req, ledger, result, true);
expect (! contains_error (result));
}
{
Json::Value req;
Json::Value result;
Json::Reader ().parse (
"{ \"fee_mult_max\" : 0, \"tx_json\" : { } } "
, req);
autofill_fee (req, ledger, result, true);
expect (contains_error (result));
}
}
void run ()
{
testAutoFillFees ();
}
};
BEAST_DEFINE_TESTSUITE(JSONRPC,ripple_app,ripple);
} // RPC
} // ripple

View File

@@ -0,0 +1,37 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#ifndef RIPPLE_RPC_TRANSACTIONSIGN_H_INCLUDED
#define RIPPLE_RPC_TRANSACTIONSIGN_H_INCLUDED
namespace ripple {
namespace RPC {
Json::Value transactionSign (
Json::Value jvRequest,
bool bSubmit,
bool bFailHard,
Application::ScopedLockType& mlh,
NetworkOPs& netOps,
int role);
} // RPC
} // ripple
#endif