mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Improved human readable JSON-RPC error messages
This commit is contained in:
208
src/ripple/rpc/api/ErrorCodes.h
Normal file
208
src/ripple/rpc/api/ErrorCodes.h
Normal file
@@ -0,0 +1,208 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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
|
||||
|
||||
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,
|
||||
|
||||
// Networking
|
||||
rpcNO_CLOSED,
|
||||
rpcNO_CURRENT,
|
||||
rpcNO_NETWORK,
|
||||
|
||||
// Ledger state
|
||||
rpcACT_EXISTS,
|
||||
rpcACT_NOT_FOUND,
|
||||
rpcINSUF_FUNDS,
|
||||
rpcLGR_NOT_FOUND,
|
||||
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_DECRPYT,
|
||||
rpcNOT_IMPL,
|
||||
rpcNOT_SUPPORTED,
|
||||
rpcNO_GEN_DECRPYT,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
169
src/ripple/rpc/impl/ErrorCodes.cpp
Normal file
169
src/ripple/rpc/impl/ErrorCodes.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace ripple {
|
||||
namespace RPC {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class ErrorCategory
|
||||
{
|
||||
public:
|
||||
typedef boost::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 (rpcFORBIDDEN, "forbidden", "Bad credentials.");
|
||||
add (rpcFAIL_GEN_DECRPYT, "failGenDecrypt", "Failed to decrypt generator.");
|
||||
add (rpcGETS_ACT_MALFORMED, "getsActMalformed", "Gets account malformed.");
|
||||
add (rpcGETS_AMT_MALFORMED, "getsAmtMalformed", "Gets amount malformed.");
|
||||
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 (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_DECRPYT, "noGenDectypt", "Password failed to decrypt master public generator.");
|
||||
add (rpcNO_NETWORK, "noNetwork", "Network not available.");
|
||||
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 (boost::unordered::piecewise_construct,
|
||||
boost::make_tuple (code), boost::make_tuple (
|
||||
code, token, message)));
|
||||
check_postcondition (result.second);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "beast/modules/beast_core/system/BeforeBoost.h"
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include "impl/ErrorCodes.cpp"
|
||||
# include "impl/ManagerImpl.h"
|
||||
#include "impl/Manager.cpp"
|
||||
#include "impl/Handler.cpp"
|
||||
|
||||
@@ -27,5 +27,6 @@
|
||||
# include "api/Handler.h"
|
||||
# include "api/Service.h"
|
||||
#include "api/Manager.h"
|
||||
#include "api/ErrorCodes.h"
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user