Merge branch 'master' of github.com:jedmccaleb/NewCoin

This commit is contained in:
JoelKatz
2012-12-03 18:08:24 -08:00
21 changed files with 1147 additions and 683 deletions

View File

@@ -282,7 +282,7 @@ void Application::loadOldLedger()
if (!lastLedger) if (!lastLedger)
{ {
std::cout << "No Ledger found?" << std::endl; cLog(lsFATAL) << "No Ledger found?" << std::endl;
exit(-1); exit(-1);
} }
lastLedger->setClosed(); lastLedger->setClosed();

View File

@@ -13,11 +13,16 @@
#include "../json/value.h" #include "../json/value.h"
#include "../json/reader.h" #include "../json/reader.h"
#include "CallRPC.h"
#include "RPC.h" #include "RPC.h"
#include "Log.h"
#include "RPCErr.h"
#include "Config.h" #include "Config.h"
#include "BitcoinUtil.h" #include "BitcoinUtil.h"
#include "CallRPC.h"
SETUP_LOG();
static inline bool isSwitchChar(char c) static inline bool isSwitchChar(char c)
{ {
#ifdef __WXMSW__ #ifdef __WXMSW__
@@ -46,73 +51,393 @@ std::string EncodeBase64(const std::string& s)
return result; return result;
} }
Json::Value RPCParser::parseAsIs(const Json::Value& jvParams)
{
return Json::Value(Json::objectValue);
}
// account_info <account>|<nickname>|<account_public_key>
// account_info <seed>|<pass_phrase>|<key> [<index>]
Json::Value RPCParser::parseAccountInfo(const Json::Value& jvParams)
{
Json::Value jvRequest(Json::objectValue);
std::string strIdent = jvParams[0u].asString();
// YYY This could be more strict and report casting errors.
int iIndex = 2 == jvParams.size() ? lexical_cast_s<int>(jvParams[1u].asString()) : 0;
RippleAddress raAddress;
if (!raAddress.setAccountPublic(strIdent) && !raAddress.setAccountID(strIdent) && !raAddress.setSeedGeneric(strIdent))
return rpcError(rpcACT_MALFORMED);
jvRequest["ident"] = strIdent;
jvRequest["index"] = iIndex;
return jvRequest;
}
// account_tx <account> <minledger> <maxledger>
// account_tx <account> <ledger>
Json::Value RPCParser::parseAccountTransactions(const Json::Value& jvParams)
{
Json::Value jvRequest(Json::objectValue);
RippleAddress raAccount;
if (jvParams.size() < 2 || jvParams.size() > 3)
return rpcError(rpcINVALID_PARAMS);
if (!raAccount.setAccountID(jvParams[0u].asString()))
return rpcError(rpcACT_MALFORMED);
// YYY This could be more strict and report casting errors.
if (jvParams.size() == 2)
{
jvRequest["ledger"] = jvParams[1u].asUInt();
}
else
{
uint32 uLedgerMin = jvParams[1u].asUInt();
uint32 uLedgerMax = jvParams[2u].asUInt();
if ((uLedgerMax < uLedgerMin) || (uLedgerMax == 0))
{
return rpcError(rpcLGR_IDXS_INVALID);
}
jvRequest["ledger_min"] = uLedgerMin;
jvRequest["ledger_max"] = uLedgerMax;
}
jvRequest["account"] = raAccount.humanAccountID();
return jvRequest;
}
// connect <ip> [port]
Json::Value RPCParser::parseConnect(const Json::Value& jvParams)
{
Json::Value jvRequest(Json::objectValue);
jvRequest["ip"] = jvParams[0u].asString();
if (jvParams.size() == 2)
jvRequest["port"] = jvParams[1u].asUInt();
return jvRequest;
}
Json::Value RPCParser::parseEvented(const Json::Value& jvParams)
{
return rpcError(rpcNO_EVENTS);
}
// ledger [id|ledger_current|ledger_closed] [full]
Json::Value RPCParser::parseLedger(const Json::Value& jvParams)
{
Json::Value jvRequest(Json::objectValue);
if (!jvParams.size())
{
return jvRequest;
}
std::string strLedger = jvParams[0u].asString();
if (strLedger == "current" || strLedger == "ledger_closed" || strLedger.length() > 12)
jvRequest["ledger"] = strLedger;
else
jvRequest["ledger"] = lexical_cast_s<uint32>(strLedger);
if (2 == jvParams.size() && jvParams[1u].asString() == "full")
{
jvRequest["full"] = bool(1);
}
return jvRequest;
}
// ripple_lines_get <account>|<nickname>|<account_public_key> [<index>]
Json::Value RPCParser::parseRippleLinesGet(const Json::Value& jvParams)
{
std::string strIdent = jvParams[0u].asString();
bool bIndex = 2 == jvParams.size();
int iIndex = bIndex ? lexical_cast_s<int>(jvParams[1u].asString()) : 0;
if (bIndex && !iIndex) // Don't send default.
bIndex = false;
// Get info on account.
Json::Value jvRequest(Json::objectValue);
jvRequest["account"] = strIdent;
if (bIndex)
jvRequest["index"] = iIndex;
return jvRequest;
}
// submit any transaction to the network
// submit private_key json
Json::Value RPCParser::parseSubmit(const Json::Value& jvParams)
{
Json::Value txJSON;
Json::Reader reader;
if (reader.parse(jvParams[1u].asString(), txJSON))
{
Json::Value jvRequest;
jvRequest["secret"] = jvParams[0u].asString();
jvRequest["tx_json"] = txJSON;
return jvRequest;
}
return rpcError(rpcINVALID_PARAMS);
}
// unl_add <domain>|<node_public> [<comment>]
Json::Value RPCParser::parseUnlAdd(const Json::Value& jvParams)
{
std::string strNode = jvParams[0u].asString();
std::string strComment = (jvParams.size() == 2) ? jvParams[1u].asString() : "";
RippleAddress naNodePublic;
if (strNode.length())
{
Json::Value jvRequest;
jvRequest["node"] = strNode;
if (strComment.length())
jvRequest["comment"] = strComment;
return jvRequest;
}
return rpcError(rpcINVALID_PARAMS);
}
// unl_delete <domain>|<public_key>
Json::Value RPCParser::parseUnlDelete(const Json::Value& jvParams)
{
Json::Value jvRequest;
jvRequest["node"] = jvParams[0u].asString();
return jvRequest;
}
// wallet_accounts <seed>
Json::Value RPCParser::parseWalletAccounts(const Json::Value& jvParams)
{
Json::Value jvRequest;
jvRequest["seed"] = jvParams[0u].asString();
return jvRequest;
}
//
// parseCommand
//
// Convert a rpc method and params to a request.
// <-- { method: xyz, params: [... ] } or { error: ..., ... }
Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams)
{
cLog(lsTRACE) << "RPC method:" << strMethod;
cLog(lsTRACE) << "RPC params:" << jvParams;
static struct {
const char* pCommand;
parseFuncPtr pfpFunc;
int iMinParams;
int iMaxParams;
} commandsA[] = {
// Request-response methods
// - Returns an error, or the request.
// - To modify the method, provide a new method in the request.
{ "accept_ledger", &RPCParser::parseAsIs, 0, 0 },
{ "account_info", &RPCParser::parseAccountInfo, 1, 2 },
{ "account_tx", &RPCParser::parseAccountTransactions, 2, 3 },
{ "connect", &RPCParser::parseConnect, 1, 2 },
// { "data_delete", &RPCParser::doDataDelete, 1, 1, true, false, optNone },
// { "data_fetch", &RPCParser::doDataFetch, 1, 1, true, false, optNone },
// { "data_store", &RPCParser::doDataStore, 2, 2, true, false, optNone },
// { "get_counts", &RPCParser::doGetCounts, 0, 1, true, false, optNone },
{ "ledger", &RPCParser::parseLedger, 0, 2 },
{ "ledger_accept", &RPCParser::parseAsIs, 0, 0 },
{ "ledger_closed", &RPCParser::parseAsIs, 0, 0 },
{ "ledger_current", &RPCParser::parseAsIs, 0, 0 },
// { "ledger_entry", &RPCParser::doLedgerEntry, -1, -1, false, false, optCurrent },
// { "ledger_header", &RPCParser::doLedgerHeader, -1, -1, false, false, optCurrent },
// { "log_level", &RPCParser::doLogLevel, 0, 2, true, false, optNone },
{ "logrotate", &RPCParser::parseAsIs, 0, 0 },
// { "nickname_info", &RPCParser::doNicknameInfo, 1, 1, false, false, optCurrent },
// { "owner_info", &RPCParser::doOwnerInfo, 1, 2, false, false, optCurrent },
{ "peers", &RPCParser::parseAsIs, 0, 0 },
// { "profile", &RPCParser::doProfile, 1, 9, false, false, optCurrent },
{ "ripple_lines_get", &RPCParser::parseRippleLinesGet, 1, 2 },
// { "ripple_path_find", &RPCParser::doRipplePathFind, -1, -1, false, false, optCurrent },
{ "submit", &RPCParser::parseSubmit, 2, 2 },
{ "server_info", &RPCParser::parseAsIs, 0, 0 },
{ "stop", &RPCParser::parseAsIs, 0, 0 },
// { "transaction_entry", &RPCParser::doTransactionEntry, -1, -1, false, false, optCurrent },
// { "tx", &RPCParser::doTx, 1, 1, true, false, optNone },
// { "tx_history", &RPCParser::doTxHistory, 1, 1, false, false, optNone },
//
{ "unl_add", &RPCParser::parseUnlAdd, 1, 2 },
{ "unl_delete", &RPCParser::parseUnlDelete, 1, 1 },
{ "unl_list", &RPCParser::parseAsIs, 0, 0 },
{ "unl_load", &RPCParser::parseAsIs, 0, 0 },
{ "unl_network", &RPCParser::parseAsIs, 0, 0 },
{ "unl_reset", &RPCParser::parseAsIs, 0, 0 },
{ "unl_score", &RPCParser::parseAsIs, 0, 0 },
// { "validation_create", &RPCParser::doValidationCreate, 0, 1, false, false, optNone },
// { "validation_seed", &RPCParser::doValidationSeed, 0, 1, false, false, optNone },
{ "wallet_accounts", &RPCParser::parseWalletAccounts, 1, 1 },
// { "wallet_propose", &RPCParser::doWalletPropose, 0, 1, false, false, optNone },
// { "wallet_seed", &RPCParser::doWalletSeed, 0, 1, false, false, optNone },
//
// { "login", &RPCParser::doLogin, 2, 2, true, false, optNone },
// Evented methods
{ "subscribe", &RPCParser::parseEvented, -1, -1 },
{ "unsubscribe", &RPCParser::parseEvented, -1, -1 },
};
int i = NUMBER(commandsA);
while (i-- && strMethod != commandsA[i].pCommand)
;
if (i < 0)
{
return rpcError(rpcBAD_SYNTAX);
}
else if ((commandsA[i].iMinParams >= 0 && jvParams.size() < commandsA[i].iMinParams)
|| (commandsA[i].iMaxParams >= 0 && jvParams.size() > commandsA[i].iMaxParams))
{
cLog(lsWARNING) << "Wrong number of parameters: minimum=" << commandsA[i].iMinParams
<< " maximum=" << commandsA[i].iMaxParams
<< " actual=" << jvParams.size();
return rpcError(rpcBAD_SYNTAX);
}
return (this->*(commandsA[i].pfpFunc))(jvParams);
}
int commandLineRPC(const std::vector<std::string>& vCmd) int commandLineRPC(const std::vector<std::string>& vCmd)
{ {
std::string strPrint; Json::Value jvOutput;
int nRet = 0; int nRet = 0;
Json::Value jvRequest(Json::objectValue);
try try
{ {
if (vCmd.empty()) return 1; RPCParser rpParser;
Json::Value jvRpcParams(Json::arrayValue);
std::string strMethod = vCmd[0]; if (vCmd.empty()) return 1; // 1 = print usage.
// Parameters default to strings
Json::Value params(Json::arrayValue);
for (int i = 1; i != vCmd.size(); i++) for (int i = 1; i != vCmd.size(); i++)
params.append(vCmd[i]); jvRpcParams.append(vCmd[i]);
// Execute Json::Value jvRpc = Json::Value(Json::objectValue);
Json::Value reply = callRPC(strMethod, params);
// Parse reply jvRpc["method"] = vCmd[0];
Json::Value result = reply.get("result", Json::Value()); jvRpc["params"] = jvRpcParams;
Json::Value error = reply.get("error", Json::Value());
if (result.isString() && (result.asString() == "unknown command")) jvRequest = rpParser.parseCommand(vCmd[0], jvRpcParams);
nRet=1;
if (!error.isNull()) // std::cerr << "Request: " << jvRequest << std::endl;
{ // Error
strPrint = "error: " + error.toStyledString(); if (jvRequest.isMember("error"))
int code = error["code"].asInt(); {
nRet = abs(code); jvOutput = jvRequest;
jvOutput["rpc"] = jvRpc;
} }
else else
{ // Result {
if (result.isNull()) Json::Value jvParams(Json::arrayValue);
strPrint = "";
else if (result.isString()) jvParams.append(jvRequest);
strPrint = result.asString();
else jvOutput = callRPC(
strPrint = result.toStyledString(); jvRequest.isMember("method") // Allow parser to rewrite method.
? jvRequest["method"].asString()
: vCmd[0],
jvParams); // Parsed, execute.
if (jvOutput.isMember("result"))
{
// Had a successful JSON-RPC 2.0 call.
jvOutput = jvOutput["result"];
// jvOutput may report a server side error.
// It should report "status".
} }
else
{
// Transport error.
Json::Value jvRpcError = jvOutput;
jvOutput = rpcError(rpcJSON_RPC);
jvOutput["result"] = jvRpcError;
}
// If had an error, supply invokation in result.
if (jvOutput.isMember("error"))
{
jvOutput["rpc"] = jvRpc; // How the command was seen as method + params.
jvOutput["request_sent"] = jvRequest; // How the command was translated.
}
}
if (jvOutput.isMember("error"))
{
jvOutput["status"] = "error";
nRet = jvOutput.isMember("error_code")
? lexical_cast_s<int>(jvOutput["error_code"].asString())
: 1;
}
// YYY We could have a command line flag for single line output for scripts.
// YYY We would intercept output here and simplify it.
} }
catch (std::exception& e) catch (std::exception& e)
{ {
strPrint = std::string("error: ") + e.what(); jvOutput = rpcError(rpcINTERNAL);
nRet = 87; jvOutput["error_what"] = e.what();
nRet = rpcINTERNAL;
} }
catch (...) catch (...)
{ {
std::cout << "Exception CommandLineRPC()" << std::endl; jvOutput = rpcError(rpcINTERNAL);
jvOutput["error_what"] = "exception";
nRet = rpcINTERNAL;
} }
if (strPrint != "") std::cout << jvOutput.toStyledString();
{
std::cout << strPrint << std::endl;
}
return nRet; return nRet;
} }
Json::Value callRPC(const std::string& strMethod, const Json::Value& params) Json::Value callRPC(const std::string& strMethod, const Json::Value& params)
{ {
if (theConfig.RPC_USER.empty() && theConfig.RPC_PASSWORD.empty()) if (theConfig.RPC_USER.empty() && theConfig.RPC_PASSWORD.empty())
throw std::runtime_error("You must set rpcpassword=<password> in the configuration file" throw std::runtime_error("You must set rpcpassword=<password> in the configuration file. "
"If the file does not exist, create it with owner-readable-only file permissions."); "If the file does not exist, create it with owner-readable-only file permissions.");
// Connect to localhost // Connect to localhost
std::cout << "Connecting to: " << theConfig.RPC_IP << ":" << theConfig.RPC_PORT << std::endl; if (!theConfig.QUIET)
std::cerr << "Connecting to: " << theConfig.RPC_IP << ":" << theConfig.RPC_PORT << std::endl;
boost::asio::ip::tcp::endpoint boost::asio::ip::tcp::endpoint
endpoint(boost::asio::ip::address::from_string(theConfig.RPC_IP), theConfig.RPC_PORT); endpoint(boost::asio::ip::address::from_string(theConfig.RPC_IP), theConfig.RPC_PORT);
@@ -128,11 +453,11 @@ Json::Value callRPC(const std::string& strMethod, const Json::Value& params)
// Send request // Send request
std::string strRequest = JSONRPCRequest(strMethod, params, Json::Value(1)); std::string strRequest = JSONRPCRequest(strMethod, params, Json::Value(1));
std::cout << "send request " << strMethod << " : " << strRequest << std::endl; cLog(lsDEBUG) << "send request " << strMethod << " : " << strRequest << std::endl;
std::string strPost = createHTTPPost(strRequest, mapRequestHeaders); std::string strPost = createHTTPPost(strRequest, mapRequestHeaders);
stream << strPost << std::flush; stream << strPost << std::flush;
// std::cout << "post " << strPost << std::endl; // std::cerr << "post " << strPost << std::endl;
// Receive reply // Receive reply
std::map<std::string, std::string> mapHeaders; std::map<std::string, std::string> mapHeaders;
@@ -146,11 +471,14 @@ Json::Value callRPC(const std::string& strMethod, const Json::Value& params)
throw std::runtime_error("no response from server"); throw std::runtime_error("no response from server");
// Parse reply // Parse reply
std::cout << "RPC reply: " << strReply << std::endl; cLog(lsDEBUG) << "RPC reply: " << strReply << std::endl;
Json::Reader reader; Json::Reader reader;
Json::Value valReply; Json::Value valReply;
if (!reader.parse(strReply, valReply)) if (!reader.parse(strReply, valReply))
throw std::runtime_error("couldn't parse reply from server"); throw std::runtime_error("couldn't parse reply from server");
if (valReply.isNull()) if (valReply.isNull())
throw std::runtime_error("expected reply to have result, error and id properties"); throw std::runtime_error("expected reply to have result, error and id properties");

View File

@@ -1,7 +1,35 @@
#ifndef __CALLRPC__
#define __CALLRPC__
#include <string> #include <string>
#include "../json/value.h" #include "../json/value.h"
class RPCParser
{
protected:
typedef Json::Value (RPCParser::*parseFuncPtr)(const Json::Value &jvParams);
Json::Value parseAsIs(const Json::Value& jvParams);
Json::Value parseAccountInfo(const Json::Value& jvParams);
Json::Value parseAccountTransactions(const Json::Value& jvParams);
Json::Value parseConnect(const Json::Value& jvParams);
Json::Value parseEvented(const Json::Value& jvParams);
Json::Value parseLedger(const Json::Value& jvParams);
Json::Value parseWalletAccounts(const Json::Value& jvParams);
Json::Value parseRippleLinesGet(const Json::Value& jvParams);
Json::Value parseSubmit(const Json::Value& jvParams);
Json::Value parseUnlAdd(const Json::Value& jvParams);
Json::Value parseUnlDelete(const Json::Value& jvParams);
public:
Json::Value parseCommand(std::string strMethod, Json::Value jvParams);
};
extern int commandLineRPC(const std::vector<std::string>& vCmd); extern int commandLineRPC(const std::vector<std::string>& vCmd);
extern Json::Value callRPC(const std::string& strMethod, const Json::Value& params); extern Json::Value callRPC(const std::string& strMethod, const Json::Value& params);
#endif
// vim:ts=4

View File

@@ -1,3 +1,6 @@
//
// TODO: Check permissions on config file before using it.
//
#include "Config.h" #include "Config.h"
#include "utils.h" #include "utils.h"
@@ -48,7 +51,7 @@
Config theConfig; Config theConfig;
void Config::setup(const std::string& strConf) void Config::setup(const std::string& strConf, bool bQuiet)
{ {
boost::system::error_code ec; boost::system::error_code ec;
@@ -58,6 +61,8 @@ void Config::setup(const std::string& strConf)
// that with "db" as the data directory. // that with "db" as the data directory.
// //
QUIET = bQuiet;
if (!strConf.empty()) if (!strConf.empty())
{ {
// --conf=<path> : everything is relative that file. // --conf=<path> : everything is relative that file.
@@ -172,7 +177,8 @@ void Config::setup(const std::string& strConf)
void Config::load() void Config::load()
{ {
std::cout << "Loading: " << CONFIG_FILE << std::endl; if (!QUIET)
std::cerr << "Loading: " << CONFIG_FILE << std::endl;
std::ifstream ifsConfig(CONFIG_FILE.c_str(), std::ios::in); std::ifstream ifsConfig(CONFIG_FILE.c_str(), std::ios::in);

View File

@@ -46,6 +46,8 @@ class Config
{ {
public: public:
// Configuration parameters // Configuration parameters
bool QUIET;
boost::filesystem::path CONFIG_FILE; boost::filesystem::path CONFIG_FILE;
boost::filesystem::path CONFIG_DIR; boost::filesystem::path CONFIG_DIR;
boost::filesystem::path DATA_DIR; boost::filesystem::path DATA_DIR;
@@ -113,7 +115,7 @@ public:
// Client behavior // Client behavior
int ACCOUNT_PROBE_MAX; // How far to scan for accounts. int ACCOUNT_PROBE_MAX; // How far to scan for accounts.
void setup(const std::string& strConf); void setup(const std::string& strConf, bool bQuiet);
void load(); void load();
}; };

View File

@@ -101,7 +101,7 @@ bool ConnectionPool::savePeer(const std::string& strIp, int iPort, char code)
} }
else else
{ {
std::cout << "Error saving Peer" << std::endl; std::cerr << "Error saving Peer" << std::endl;
} }
if (bNew) if (bNew)

View File

@@ -54,7 +54,7 @@ void PeerDoor::handleConnect(Peer::pointer new_connection,
{ {
new_connection->connected(error); new_connection->connected(error);
} }
else cout << "Error: " << error; else cerr << "Error: " << error;
startListening(); startListening();
} }

84
src/cpp/ripple/RPCErr.cpp Normal file
View File

@@ -0,0 +1,84 @@
#include "Log.h"
#include "RPCErr.h"
#include "utils.h"
#include "../json/writer.h"
SETUP_LOG();
Json::Value rpcError(int iError, Json::Value jvResult)
{
static struct {
int iError;
const char* pToken;
const char* pMessage;
} errorInfoA[] = {
{ rpcACT_EXISTS, "actExists", "Account already exists." },
{ rpcACT_MALFORMED, "actMalformed", "Account malformed." },
{ rpcACT_NOT_FOUND, "actNotFound", "Account not found." },
{ rpcBAD_SEED, "badSeed", "Disallowed seed." },
{ rpcBAD_SYNTAX, "badSyntax", "Syntax error." },
{ rpcDST_ACT_MALFORMED, "dstActMalformed", "Destination account is malformed." },
{ rpcDST_ACT_MISSING, "dstActMissing", "Destination account does not exists." },
{ rpcDST_AMT_MALFORMED, "dstAmtMalformed", "Destination amount/currency/issuer is malformed." },
{ rpcFAIL_GEN_DECRPYT, "failGenDecrypt", "Failed to decrypt generator." },
{ rpcGETS_ACT_MALFORMED, "getsActMalformed", "Gets account malformed." },
{ rpcGETS_AMT_MALFORMED, "getsAmtMalformed", "Gets amount malformed." },
{ rpcHOST_IP_MALFORMED, "hostIpMalformed", "Host IP is malformed." },
{ rpcINSUF_FUNDS, "insufFunds", "Insufficient funds." },
{ rpcINTERNAL, "internal", "Internal error." },
{ rpcINVALID_PARAMS, "invalidParams", "Invalid parameters." },
{ rpcJSON_RPC, "json_rpc", "JSON-RPC transport error." },
{ rpcLGR_IDXS_INVALID, "lgrIdxsInvalid", "Ledger indexes invalid." },
{ rpcLGR_IDX_MALFORMED, "lgrIdxMalformed", "Ledger index malformed." },
{ rpcLGR_NOT_FOUND, "lgrNotFound", "Ledger not found." },
{ rpcNICKNAME_MALFORMED, "nicknameMalformed","Nickname is malformed." },
{ rpcNICKNAME_MISSING, "nicknameMissing", "Nickname does not exist." },
{ rpcNICKNAME_PERM, "nicknamePerm", "Account does not control nickname." },
{ rpcNOT_IMPL, "notImpl", "Not implemented." },
{ rpcNO_ACCOUNT, "noAccount", "No such account." },
{ rpcNO_CLOSED, "noClosed", "Closed ledger is unavailable." },
{ rpcNO_CURRENT, "noCurrent", "Current ledger is unavailable." },
{ rpcNO_EVENTS, "noEvents", "Current transport does not support events." },
{ rpcNO_GEN_DECRPYT, "noGenDectypt", "Password failed to decrypt master public generator." },
{ rpcNO_NETWORK, "noNetwork", "Network not available." },
{ rpcNO_PATH, "noPath", "Unable to find a ripple path." },
{ rpcNO_PERMISSION, "noPermission", "You don't have permission for this command." },
{ rpcNOT_STANDALONE, "notStandAlone", "Operation valid in debug mode only." },
{ rpcPASSWD_CHANGED, "passwdChanged", "Wrong key, password changed." },
{ rpcPAYS_ACT_MALFORMED, "paysActMalformed", "Pays account malformed." },
{ rpcPAYS_AMT_MALFORMED, "paysAmtMalformed", "Pays amount malformed." },
{ rpcPORT_MALFORMED, "portMalformed", "Port is malformed." },
{ rpcPUBLIC_MALFORMED, "publicMalformed", "Public key is malformed." },
{ rpcQUALITY_MALFORMED, "qualityMalformed", "Quality malformed." },
{ rpcSRC_ACT_MALFORMED, "srcActMalformed", "Source account is malformed." },
{ rpcSRC_ACT_MISSING, "srcActMissing", "Source account does not exist." },
{ rpcSRC_AMT_MALFORMED, "srcAmtMalformed", "Source amount/currency/issuer is malformed." },
{ rpcSRC_UNCLAIMED, "srcUnclaimed", "Source account is not claimed." },
{ rpcSUCCESS, "success", "Success." },
{ rpcTXN_NOT_FOUND, "txnNotFound", "Transaction not found." },
{ rpcUNKNOWN_COMMAND, "unknownCmd", "Unknown command." },
{ rpcWRONG_SEED, "wrongSeed", "The regular key does not point as the master key." },
};
int i;
for (i=NUMBER(errorInfoA); i-- && errorInfoA[i].iError != iError;)
;
jvResult["error"] = i >= 0 ? errorInfoA[i].pToken : lexical_cast_i(iError);
jvResult["error_message"] = i >= 0 ? errorInfoA[i].pMessage : lexical_cast_i(iError);
jvResult["error_code"] = iError;
if (i >= 0)
{
cLog(lsDEBUG) << "rpcError: "
<< errorInfoA[i].pToken << ": " << errorInfoA[i].pMessage << std::endl;
}
return jvResult;
}
// vim:ts=4

75
src/cpp/ripple/RPCErr.h Normal file
View File

@@ -0,0 +1,75 @@
#ifndef __RPCERR__
#define __RPCERR__
#include "../json/value.h"
enum {
rpcSUCCESS,
rpcBAD_SYNTAX, // Must be 1 to print usage to command line.
rpcJSON_RPC,
// 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,
// 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,
// Bad parameter
rpcACT_MALFORMED,
rpcQUALITY_MALFORMED,
rpcBAD_SEED,
rpcDST_ACT_MALFORMED,
rpcDST_ACT_MISSING,
rpcDST_AMT_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_AMT_MALFORMED,
// Internal error (should never happen)
rpcINTERNAL, // Generic internal error.
rpcFAIL_GEN_DECRPYT,
rpcNOT_IMPL,
rpcNO_GEN_DECRPYT,
};
Json::Value rpcError(int iError, Json::Value jvResult=Json::Value(Json::objectValue));
#endif
// vim:ts=4

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
#ifndef RPCHANDLER__H #ifndef __RPCHANDLER__
#define RPCHANDLER__H #define __RPCHANDLER__
// used by the RPCServer or WSDoor to carry out these RPC commands // used by the RPCServer or WSDoor to carry out these RPC commands
class NetworkOPs; class NetworkOPs;
@@ -10,7 +10,7 @@ class RPCHandler
InfoSub* mInfoSub; InfoSub* mInfoSub;
int mRole; int mRole;
typedef Json::Value (RPCHandler::*doFuncPtr)(const Json::Value& params); typedef Json::Value (RPCHandler::*doFuncPtr)(Json::Value params);
enum { enum {
optNone = 0, optNone = 0,
optNetwork = 1, // Need network optNetwork = 1, // Need network
@@ -21,10 +21,10 @@ class RPCHandler
// Utilities // Utilities
void addSubmitPath(Json::Value& txJSON); void addSubmitPath(Json::Value& txJSON);
boost::unordered_set<RippleAddress> parseAccountIds(const Json::Value& jvArray); boost::unordered_set<RippleAddress> parseAccountIds(const Json::Value& jvArray);
int getParamCount(const Json::Value& params); int getParamCount(Json::Value params);
bool extractString(std::string& param, const Json::Value& params, int index); bool extractString(std::string& param, const Json::Value& params, int index);
Json::Value lookupLedger(const Json::Value& jvRequest, Ledger::pointer& lpLedger); Json::Value lookupLedger(Json::Value jvRequest, Ledger::pointer& lpLedger);
Json::Value getMasterGenerator(const uint256& uLedger, const RippleAddress& naRegularSeed, RippleAddress& naMasterGenerator); Json::Value getMasterGenerator(const uint256& uLedger, const RippleAddress& naRegularSeed, RippleAddress& naMasterGenerator);
Json::Value authorize(const uint256& uLedger, const RippleAddress& naRegularSeed, const RippleAddress& naSrcAccountID, Json::Value authorize(const uint256& uLedger, const RippleAddress& naRegularSeed, const RippleAddress& naSrcAccountID,
@@ -35,142 +35,78 @@ class RPCHandler
Json::Value accountFromString(const uint256& uLedger, RippleAddress& naAccount, bool& bIndex, const std::string& strIdent, const int iIndex); Json::Value accountFromString(const uint256& uLedger, RippleAddress& naAccount, bool& bIndex, const std::string& strIdent, const int iIndex);
Json::Value doAcceptLedger(const Json::Value& params); Json::Value doAcceptLedger(Json::Value jvRequest);
Json::Value doAccountInfo(const Json::Value& params); Json::Value doAccountInfo(Json::Value params);
Json::Value doAccountTransactions(const Json::Value& params); Json::Value doAccountTransactions(Json::Value params);
Json::Value doConnect(const Json::Value& params); Json::Value doConnect(Json::Value params);
Json::Value doDataDelete(const Json::Value& params); Json::Value doDataDelete(Json::Value params);
Json::Value doDataFetch(const Json::Value& params); Json::Value doDataFetch(Json::Value params);
Json::Value doDataStore(const Json::Value& params); Json::Value doDataStore(Json::Value params);
Json::Value doGetCounts(const Json::Value& params); Json::Value doGetCounts(Json::Value params);
Json::Value doLedger(const Json::Value& params); Json::Value doLedger(Json::Value params);
Json::Value doLogRotate(const Json::Value& params); Json::Value doLogRotate(Json::Value params);
Json::Value doNicknameInfo(const Json::Value& params); Json::Value doNicknameInfo(Json::Value params);
Json::Value doOwnerInfo(const Json::Value& params); Json::Value doOwnerInfo(Json::Value params);
Json::Value doProfile(const Json::Value& params); Json::Value doProfile(Json::Value params);
Json::Value doPeers(const Json::Value& params); Json::Value doPeers(Json::Value params);
Json::Value doRippleLinesGet(const Json::Value& params); Json::Value doRippleLinesGet(Json::Value params);
Json::Value doRipplePathFind(const Json::Value& jvRequest); Json::Value doRipplePathFind(Json::Value jvRequest);
Json::Value doServerInfo(const Json::Value& params); Json::Value doServerInfo(Json::Value params);
Json::Value doSessionClose(const Json::Value& params); Json::Value doSessionClose(Json::Value params);
Json::Value doSessionOpen(const Json::Value& params); Json::Value doSessionOpen(Json::Value params);
Json::Value doLogLevel(const Json::Value& params); Json::Value doLogLevel(Json::Value params);
Json::Value doStop(const Json::Value& params); Json::Value doStop(Json::Value params);
Json::Value doSubmit(const Json::Value& params); Json::Value doSubmit(Json::Value params);
Json::Value doSubmitJson(const Json::Value& jvRequest); Json::Value doTx(Json::Value params);
Json::Value doTx(const Json::Value& params); Json::Value doTxHistory(Json::Value params);
Json::Value doTxHistory(const Json::Value& params);
Json::Value doUnlAdd(const Json::Value& params); Json::Value doUnlAdd(Json::Value params);
Json::Value doUnlDelete(const Json::Value& params); Json::Value doUnlDelete(Json::Value params);
Json::Value doUnlFetch(const Json::Value& params); Json::Value doUnlFetch(Json::Value params);
Json::Value doUnlList(const Json::Value& params); Json::Value doUnlList(Json::Value params);
Json::Value doUnlLoad(const Json::Value& params); Json::Value doUnlLoad(Json::Value params);
Json::Value doUnlNetwork(const Json::Value& params); Json::Value doUnlNetwork(Json::Value params);
Json::Value doUnlReset(const Json::Value& params); Json::Value doUnlReset(Json::Value params);
Json::Value doUnlScore(const Json::Value& params); Json::Value doUnlScore(Json::Value params);
Json::Value doValidationCreate(const Json::Value& params); Json::Value doValidationCreate(Json::Value params);
Json::Value doValidationSeed(const Json::Value& params); Json::Value doValidationSeed(Json::Value params);
Json::Value doWalletAccounts(const Json::Value& params); Json::Value doWalletAccounts(Json::Value params);
Json::Value doWalletLock(const Json::Value& params); Json::Value doWalletLock(Json::Value params);
Json::Value doWalletPropose(const Json::Value& params); Json::Value doWalletPropose(Json::Value params);
Json::Value doWalletSeed(const Json::Value& params); Json::Value doWalletSeed(Json::Value params);
Json::Value doWalletUnlock(const Json::Value& params); Json::Value doWalletUnlock(Json::Value params);
Json::Value doWalletVerify(const Json::Value& params); Json::Value doWalletVerify(Json::Value params);
Json::Value doLogin(const Json::Value& params); Json::Value doLogin(Json::Value params);
Json::Value doLedgerAccept(const Json::Value& params); Json::Value doLedgerAccept(Json::Value params);
Json::Value doLedgerClosed(const Json::Value& params); Json::Value doLedgerClosed(Json::Value params);
Json::Value doLedgerCurrent(const Json::Value& params); Json::Value doLedgerCurrent(Json::Value params);
Json::Value doLedgerEntry(const Json::Value& params); Json::Value doLedgerEntry(Json::Value params);
Json::Value doLedgerHeader(const Json::Value& params); Json::Value doLedgerHeader(Json::Value params);
Json::Value doTransactionEntry(const Json::Value& params); Json::Value doTransactionEntry(Json::Value params);
Json::Value doSubscribe(const Json::Value& params); Json::Value doSubscribe(Json::Value params);
Json::Value doUnsubscribe(const Json::Value& params); Json::Value doUnsubscribe(Json::Value params);
public: public:
enum {
rpcSUCCESS,
// Misc failure
rpcLOAD_FAILED,
rpcNO_PERMISSION,
rpcNO_EVENTS,
rpcNOT_STANDALONE,
// 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,
// Bad parameter
rpcACT_MALFORMED,
rpcQUALITY_MALFORMED,
rpcBAD_SEED,
rpcDST_ACT_MALFORMED,
rpcDST_ACT_MISSING,
rpcDST_AMT_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_AMT_MALFORMED,
// Internal error (should never happen)
rpcINTERNAL, // Generic internal error.
rpcFAIL_GEN_DECRPYT,
rpcNOT_IMPL,
rpcNO_GEN_DECRPYT,
};
enum { GUEST, USER, ADMIN }; enum { GUEST, USER, ADMIN };
RPCHandler(NetworkOPs* netOps); RPCHandler(NetworkOPs* netOps);
RPCHandler(NetworkOPs* netOps, InfoSub* infoSub); RPCHandler(NetworkOPs* netOps, InfoSub* infoSub);
Json::Value doCommand(const std::string& command, Json::Value& params, int role); Json::Value doCommand(Json::Value& jvRequest, int role);
Json::Value rpcError(int iError); Json::Value doRpcCommand(const std::string& strCommand, Json::Value& jvParams, int iRole);
Json::Value handleJSONSubmit(const Json::Value& jvRequest);
}; };
#endif #endif

View File

@@ -36,7 +36,7 @@ RPCServer::RPCServer(boost::asio::io_service& io_service , NetworkOPs* nopNetwor
void RPCServer::connected() void RPCServer::connected()
{ {
//std::cout << "RPC request" << std::endl; //std::cerr << "RPC request" << std::endl;
if (mSocket.remote_endpoint().address().to_string()=="127.0.0.1") mRole = RPCHandler::ADMIN; if (mSocket.remote_endpoint().address().to_string()=="127.0.0.1") mRole = RPCHandler::ADMIN;
else mRole = RPCHandler::GUEST; else mRole = RPCHandler::GUEST;
@@ -145,7 +145,7 @@ std::string RPCServer::handleRequest(const std::string& requestStr)
RPCHandler mRPCHandler(mNetOps); RPCHandler mRPCHandler(mNetOps);
cLog(lsTRACE) << valParams; cLog(lsTRACE) << valParams;
Json::Value result = mRPCHandler.doCommand(strMethod, valParams,mRole); Json::Value result = mRPCHandler.doRpcCommand(strMethod, valParams, mRole);
cLog(lsTRACE) << result; cLog(lsTRACE) << result;
std::string strReply = JSONRPCReply(result, Json::Value(), id); std::string strReply = JSONRPCReply(result, Json::Value(), id);
@@ -167,7 +167,7 @@ bool RPCServer::parseAcceptRate(const std::string& sAcceptRate)
void RPCServer::handle_write(const boost::system::error_code& e) void RPCServer::handle_write(const boost::system::error_code& e)
{ {
//std::cout << "async_write complete " << e << std::endl; //std::cerr << "async_write complete " << e << std::endl;
if (!e) if (!e)
{ {

View File

@@ -15,9 +15,9 @@ RippleLines::RippleLines(const uint160& accountID, Ledger::ref ledger)
void RippleLines::printRippleLines() void RippleLines::printRippleLines()
{ {
for (unsigned int i =0; i < mLines.size(); i++) { for (unsigned int i =0; i < mLines.size(); i++) {
std::cout << i << ": " << mLines[i]->getAccountID().humanAccountID() << std::endl; std::cerr << i << ": " << mLines[i]->getAccountID().humanAccountID() << std::endl;
} }
std::cout << std::endl; std::cerr << std::endl;
} }
RippleLines::RippleLines(const uint160& accountID ) RippleLines::RippleLines(const uint160& accountID )

View File

@@ -30,25 +30,25 @@ SerializedType& SerializedType::operator=(const SerializedType& t)
void STPathSet::printDebug() { void STPathSet::printDebug() {
for (int i = 0; i < value.size(); i++) { for (int i = 0; i < value.size(); i++) {
std::cout << i << ": "; std::cerr << i << ": ";
for (int j = 0; j < value[i].mPath.size(); j++) { for (int j = 0; j < value[i].mPath.size(); j++) {
//STPathElement pe = value[i].mPath[j]; //STPathElement pe = value[i].mPath[j];
RippleAddress nad; RippleAddress nad;
nad.setAccountID(value[i].mPath[j].mAccountID); nad.setAccountID(value[i].mPath[j].mAccountID);
std::cout << " " << nad.humanAccountID(); std::cerr << " " << nad.humanAccountID();
//std::cout << " " << pe.mAccountID.GetHex(); //std::cerr << " " << pe.mAccountID.GetHex();
} }
std::cout << std::endl; std::cerr << std::endl;
} }
} }
void STPath::printDebug() { void STPath::printDebug() {
std::cout << "STPath:" << std::endl; std::cerr << "STPath:" << std::endl;
for(int i =0; i < mPath.size(); i++) { for(int i =0; i < mPath.size(); i++) {
RippleAddress nad; RippleAddress nad;
nad.setAccountID(mPath[i].mAccountID); nad.setAccountID(mPath[i].mAccountID);
std::cout << " " << i << ": " << nad.humanAccountID() << std::endl; std::cerr << " " << i << ": " << nad.humanAccountID() << std::endl;
} }
} }

View File

@@ -6,6 +6,7 @@
SETUP_LOG(); SETUP_LOG();
#include "CallRPC.h" // XXX Remove this, don't provide support for RPC syntax.
#include "WSConnection.h" #include "WSConnection.h"
#include "WSHandler.h" #include "WSHandler.h"
@@ -48,24 +49,42 @@ Json::Value WSConnection::invokeCommand(Json::Value& jvRequest)
RPCHandler mRPCHandler(&mNetwork, this); RPCHandler mRPCHandler(&mNetwork, this);
Json::Value jvResult(Json::objectValue); Json::Value jvResult(Json::objectValue);
// Regular RPC command // XXX Temporarily support RPC style commands over websocket. Remove this.
if (jvRequest.isMember("params"))
{
RPCParser rpParser;
Json::Value jvRpcRequest = rpParser.parseCommand(jvRequest["command"].asString(), jvRequest["params"]);
if (jvRpcRequest.isMember("error"))
{
jvResult = jvRpcRequest;
}
else
{ {
jvResult["result"] = mRPCHandler.doCommand( jvResult["result"] = mRPCHandler.doCommand(
jvRequest["command"].asString(), jvRpcRequest,
jvRequest.isMember("params") mHandler->getPublic() ? RPCHandler::GUEST : RPCHandler::ADMIN);
? jvRequest["params"] }
: jvRequest, }
else
{
jvResult["result"] = mRPCHandler.doCommand(
jvRequest,
mHandler->getPublic() ? RPCHandler::GUEST : RPCHandler::ADMIN); mHandler->getPublic() ? RPCHandler::GUEST : RPCHandler::ADMIN);
} }
// Currently we will simply unwrap errors returned by the RPC // Currently we will simply unwrap errors returned by the RPC
// API, in the future maybe we can make the responses // API, in the future maybe we can make the responses
// consistent. // consistent.
if (jvResult["result"].isObject() && jvResult["result"].isMember("error")) //
// Regularize result. This is duplicate code.
if (jvResult["result"].isMember("error"))
{ {
jvResult = jvResult["result"]; jvResult = jvResult["result"];
jvResult["status"] = "error"; jvResult["status"] = "error";
jvResult["request"] = jvRequest; jvResult["request"] = jvRequest;
} else { } else {
jvResult["status"] = "success"; jvResult["status"] = "success";
} }

View File

@@ -33,51 +33,51 @@ bool init_unit_test()
void printHelp(const po::options_description& desc) void printHelp(const po::options_description& desc)
{ {
cout << SYSTEM_NAME "d [options] <command> <params>" << endl; cerr << SYSTEM_NAME "d [options] <command> <params>" << endl;
cout << desc << endl; cerr << desc << endl;
cout << "Commands: " << endl; cerr << "Commands: " << endl;
cout << " account_domain_set <seed> <paying_account> [<domain>]" << endl; cerr << " account_domain_set <seed> <paying_account> [<domain>]" << endl;
cout << " account_email_set <seed> <paying_account> [<email_address>]" << endl; cerr << " account_email_set <seed> <paying_account> [<email_address>]" << endl;
cout << " account_info <account>|<nickname>" << endl; cerr << " account_info <account>|<nickname>" << endl;
cout << " account_info <seed>|<pass_phrase>|<key> [<index>]" << endl; cerr << " account_info <seed>|<pass_phrase>|<key> [<index>]" << endl;
cout << " account_message_set <seed> <paying_account> <pub_key>" << endl; cerr << " account_message_set <seed> <paying_account> <pub_key>" << endl;
cout << " account_publish_set <seed> <paying_account> <hash> <size>" << endl; cerr << " account_publish_set <seed> <paying_account> <hash> <size>" << endl;
cout << " account_rate_set <seed> <paying_account> <rate>" << endl; cerr << " account_rate_set <seed> <paying_account> <rate>" << endl;
cout << " account_wallet_set <seed> <paying_account> [<wallet_hash>]" << endl; cerr << " account_wallet_set <seed> <paying_account> [<wallet_hash>]" << endl;
cout << " connect <ip> [<port>]" << endl; cerr << " connect <ip> [<port>]" << endl;
cout << " data_delete <key>" << endl; cerr << " data_delete <key>" << endl;
cout << " data_fetch <key>" << endl; cerr << " data_fetch <key>" << endl;
cout << " data_store <key> <value>" << endl; cerr << " data_store <key> <value>" << endl;
cout << " ledger [<id>|current|lastclosed] [full]" << endl; cerr << " ledger [<id>|current|lastclosed] [full]" << endl;
cout << " logrotate " << endl; cerr << " logrotate " << endl;
cout << " nickname_info <nickname>" << endl; cerr << " nickname_info <nickname>" << endl;
cout << " nickname_set <seed> <paying_account> <nickname> [<offer_minimum>] [<authorization>]" << endl; cerr << " nickname_set <seed> <paying_account> <nickname> [<offer_minimum>] [<authorization>]" << endl;
cout << " offer_create <seed> <paying_account> <taker_pays_amount> <taker_pays_currency> <taker_pays_issuer> <takers_gets_amount> <takers_gets_currency> <takers_gets_issuer> <expires> [passive]" << endl; cerr << " offer_create <seed> <paying_account> <taker_pays_amount> <taker_pays_currency> <taker_pays_issuer> <takers_gets_amount> <takers_gets_currency> <takers_gets_issuer> <expires> [passive]" << endl;
cout << " offer_cancel <seed> <paying_account> <sequence>" << endl; cerr << " offer_cancel <seed> <paying_account> <sequence>" << endl;
cout << " password_fund <seed> <paying_account> [<account>]" << endl; cerr << " password_fund <seed> <paying_account> [<account>]" << endl;
cout << " password_set <master_seed> <regular_seed> [<account>]" << endl; cerr << " password_set <master_seed> <regular_seed> [<account>]" << endl;
cout << " peers" << endl; cerr << " peers" << endl;
cout << " ripple ..." << endl; cerr << " ripple ..." << endl;
cout << " ripple_lines_get <account>|<nickname>|<account_public_key> [<index>]" << endl; cerr << " ripple_lines_get <account>|<nickname>|<account_public_key> [<index>]" << endl;
cout << " ripple_line_set <seed> <paying_account> <destination_account> <limit_amount> <currency> [<quality_in>] [<quality_out>]" << endl; cerr << " ripple_line_set <seed> <paying_account> <destination_account> <limit_amount> <currency> [<quality_in>] [<quality_out>]" << endl;
cout << " send <seed> <paying_account> <account_id> <amount> [<currency>] [<send_max>] [<send_currency>]" << endl; cerr << " send <seed> <paying_account> <account_id> <amount> [<currency>] [<send_max>] [<send_currency>]" << endl;
cout << " stop" << endl; cerr << " stop" << endl;
cout << " tx <id>" << endl; cerr << " tx <id>" << endl;
cout << " unl_add <domain>|<public> [<comment>]" << endl; cerr << " unl_add <domain>|<public> [<comment>]" << endl;
cout << " unl_delete <domain>|<public_key>" << endl; cerr << " unl_delete <domain>|<public_key>" << endl;
cout << " unl_list" << endl; cerr << " unl_list" << endl;
cout << " unl_load" << endl; cerr << " unl_load" << endl;
cout << " unl_network" << endl; cerr << " unl_network" << endl;
cout << " unl_reset" << endl; cerr << " unl_reset" << endl;
cout << " validation_create [<seed>|<pass_phrase>|<key>]" << endl; cerr << " validation_create [<seed>|<pass_phrase>|<key>]" << endl;
cout << " validation_seed [<seed>|<pass_phrase>|<key>]" << endl; cerr << " validation_seed [<seed>|<pass_phrase>|<key>]" << endl;
cout << " wallet_add <regular_seed> <paying_account> <master_seed> [<initial_funds>] [<account_annotation>]" << endl; cerr << " wallet_add <regular_seed> <paying_account> <master_seed> [<initial_funds>] [<account_annotation>]" << endl;
cout << " wallet_accounts <seed>" << endl; cerr << " wallet_accounts <seed>" << endl;
cout << " wallet_claim <master_seed> <regular_seed> [<source_tag>] [<account_annotation>]" << endl; cerr << " wallet_claim <master_seed> <regular_seed> [<source_tag>] [<account_annotation>]" << endl;
cout << " wallet_seed [<seed>|<passphrase>|<passkey>]" << endl; cerr << " wallet_seed [<seed>|<passphrase>|<passkey>]" << endl;
cout << " wallet_propose [<passphrase>]" << endl; cerr << " wallet_propose [<passphrase>]" << endl;
} }
int main(int argc, char* argv[]) int main(int argc, char* argv[])
@@ -96,6 +96,7 @@ int main(int argc, char* argv[])
("standalone,a", "Run with no peers.") ("standalone,a", "Run with no peers.")
("test,t", "Perform unit tests.") ("test,t", "Perform unit tests.")
("parameters", po::value< vector<string> >(), "Specify comma separated parameters.") ("parameters", po::value< vector<string> >(), "Specify comma separated parameters.")
("quiet,q", "Reduce diagnotics.")
("verbose,v", "Increase log level.") ("verbose,v", "Increase log level.")
("load", "Load the current ledger from the local DB.") ("load", "Load the current ledger from the local DB.")
("start", "Start from a fresh Ledger.") ("start", "Start from a fresh Ledger.")
@@ -138,7 +139,6 @@ int main(int argc, char* argv[])
} }
} }
if (vm.count("verbose")) if (vm.count("verbose"))
Log::setMinSeverity(lsTRACE, true); Log::setMinSeverity(lsTRACE, true);
else else
@@ -152,7 +152,9 @@ int main(int argc, char* argv[])
if (!iResult) if (!iResult)
{ {
theConfig.setup(vm.count("conf") ? vm["conf"].as<std::string>() : ""); theConfig.setup(
vm.count("conf") ? vm["conf"].as<std::string>() : "", // Config file.
!!vm.count("quiet")); // Quiet flag.
if (vm.count("standalone")) if (vm.count("standalone"))
{ {
@@ -185,7 +187,7 @@ int main(int argc, char* argv[])
iResult = commandLineRPC(vCmd); iResult = commandLineRPC(vCmd);
} }
if (1 == iResult) if (1 == iResult && !vm.count("quiet"))
printHelp(desc); printHelp(desc);
return iResult; return iResult;

View File

@@ -513,6 +513,7 @@ Amount.prototype.to_human = function (opts)
} }
var formatted = ''; var formatted = '';
if (opts.signed && this._is_negative) formatted += "- ";
formatted += int_part.length ? int_part : '0'; formatted += int_part.length ? int_part : '0';
formatted += fraction_part.length ? '.'+fraction_part : ''; formatted += fraction_part.length ? '.'+fraction_part : '';

View File

@@ -548,13 +548,18 @@ Remote.prototype.request_server_info = function () {
return new Request(this, 'server_info'); return new Request(this, 'server_info');
}; };
Remote.prototype.request_ledger = function (params) { // XXX This is a bad command. Some varients don't scale.
// XXX Does this require the server to be trusted? // XXX Require the server to be trusted.
Remote.prototype.request_ledger = function (ledger, full) {
//assert(this.trusted); //assert(this.trusted);
var request = new Request(this, 'ledger'); var request = new Request(this, 'ledger');
request.message.params = params; if (ledger)
request.message.ledger = ledger;
if (full)
request.message.full = true;
return request; return request;
}; };
@@ -693,38 +698,45 @@ Remote.prototype.request_transaction_entry = function (hash) {
.tx_hash(hash); .tx_hash(hash);
}; };
Remote.prototype.request_ripple_lines_get = function (accountID) { Remote.prototype.request_ripple_lines_get = function (accountID, index) {
// XXX Does this require the server to be trusted? // XXX Does this require the server to be trusted?
//assert(this.trusted); //assert(this.trusted);
var request = new Request(this, 'ripple_lines_get'); var request = new Request(this, 'ripple_lines_get');
// XXX Convert API call to JSON request.message.account = accountID;
request.message.params = [accountID];
if (index)
request.message.index = index;
return request; return request;
}; };
Remote.prototype.request_wallet_accounts = function (key) { Remote.prototype.request_wallet_accounts = function (seed) {
// XXX Does this require the server to be trusted? assert(this.trusted); // Don't send secrets.
//assert(this.trusted);
var request = new Request(this, 'wallet_accounts'); var request = new Request(this, 'wallet_accounts');
// XXX Convert API call to JSON request.message.seed = seed;
request.message.params = [key];
return request; return request;
}; };
Remote.prototype.request_account_tx = function (accountID, minLedger, maxLedger) { Remote.prototype.request_account_tx = function (accountID, ledger_min, ledger_max) {
// XXX Does this require the server to be trusted? // XXX Does this require the server to be trusted?
//assert(this.trusted); //assert(this.trusted);
var request = new Request(this, 'account_tx'); var request = new Request(this, 'account_tx');
// XXX Convert API call to JSON request.message.account = accountID;
request.message.params = [accountID, minLedger, maxLedger];
if (ledger_min === ledger_max) {
request.message.ledger = ledger_min;
}
else {
request.message.ledger_min = ledger_min;
request.message.ledger_max = ledger_max;
}
return request; return request;
}; };
@@ -773,7 +785,7 @@ Remote.prototype.submit = function (transaction) {
else { else {
// Convert the transaction into a request and submit it. // Convert the transaction into a request and submit it.
(new Request(this, 'submit_json')) (new Request(this, 'submit'))
.build_path(transaction._build_path) .build_path(transaction._build_path)
.tx_json(transaction.tx_json) .tx_json(transaction.tx_json)
.secret(transaction._secret) .secret(transaction._secret)
@@ -803,7 +815,7 @@ Remote.prototype._server_subscribe = function () {
self._ledger_hash = message.ledger_hash; self._ledger_hash = message.ledger_hash;
self._ledger_current_index = message.ledger_index+1; self._ledger_current_index = message.ledger_index+1;
self.emit('ledger_closed', self._ledger_hash, self._ledger_current_index-1); self.emit('ledger_closed', message);
} }
self.emit('subscribed'); self.emit('subscribed');
@@ -996,18 +1008,22 @@ Remote.prototype.request_unl_list = function () {
return new Request(this, 'unl_list'); return new Request(this, 'unl_list');
}; };
Remote.prototype.request_unl_add = function (addr, note) { Remote.prototype.request_unl_add = function (addr, comment) {
var request = new Request(this, 'unl_add'); var request = new Request(this, 'unl_add');
request.message.params = [addr, note]; request.message.node = addr;
if (comment !== undefined)
request.message.comment = note;
return request; return request;
}; };
Remote.prototype.request_unl_delete = function (publicKey) { // --> node: <domain> | <public_key>
Remote.prototype.request_unl_delete = function (node) {
var request = new Request(this, 'unl_delete'); var request = new Request(this, 'unl_delete');
request.message.params = [publicKey]; request.message.node = node;
return request; return request;
}; };
@@ -1019,7 +1035,10 @@ Remote.prototype.request_peers = function () {
Remote.prototype.request_connect = function (ip, port) { Remote.prototype.request_connect = function (ip, port) {
var request = new Request(this, 'connect'); var request = new Request(this, 'connect');
request.message.params = [ip, port]; request.message.ip = ip;
if (port)
request.message.port = port;
return request; return request;
}; };
@@ -1209,7 +1228,9 @@ Transaction.prototype.submit = function (callback) {
this.submit_index = this.remote._ledger_current_index; this.submit_index = this.remote._ledger_current_index;
// When a ledger closes, look for the result. // When a ledger closes, look for the result.
var on_ledger_closed = function (ledger_hash, ledger_index) { var on_ledger_closed = function (message) {
var ledger_hash = message.ledger_hash;
var ledger_index = message.ledger_index;
var stop = false; var stop = false;
// XXX make sure self.hash is available. // XXX make sure self.hash is available.

View File

@@ -29,7 +29,7 @@ buster.testCase("//Monitor account", {
function (callback) { function (callback) {
self.what = "Close ledger."; self.what = "Close ledger.";
self.remote.once('ledger_closed', function (ledger_closed, ledger_index) { self.remote.once('ledger_closed', function () {
callback(); callback();
}); });

View File

@@ -57,7 +57,7 @@ buster.testCase("Offer tests", {
}, },
function (m, callback) { function (m, callback) {
self.remote self.remote
.once('ledger_closed', function (ledger_hash, ledger_index) { .once('ledger_closed', function (message) {
// console.log("LEDGER_CLOSED: %d: %s", ledger_index, ledger_hash); // console.log("LEDGER_CLOSED: %d: %s", ledger_index, ledger_hash);
}) })
.ledger_accept(); .ledger_accept();
@@ -101,7 +101,7 @@ buster.testCase("Offer tests", {
function (callback) { function (callback) {
if (!final_create) { if (!final_create) {
self.remote self.remote
.once('ledger_closed', function (ledger_hash, ledger_index) { .once('ledger_closed', function (mesage) {
// console.log("LEDGER_CLOSED: %d: %s", ledger_index, ledger_hash); // console.log("LEDGER_CLOSED: %d: %s", ledger_index, ledger_hash);
}) })
@@ -133,7 +133,7 @@ buster.testCase("Offer tests", {
// See if ledger_accept will crash. // See if ledger_accept will crash.
function (callback) { function (callback) {
self.remote self.remote
.once('ledger_closed', function (ledger_hash, ledger_index) { .once('ledger_closed', function (mesage) {
// console.log("LEDGER_CLOSED: A: %d: %s", ledger_index, ledger_hash); // console.log("LEDGER_CLOSED: A: %d: %s", ledger_index, ledger_hash);
callback(); callback();
}) })
@@ -141,7 +141,7 @@ buster.testCase("Offer tests", {
}, },
function (callback) { function (callback) {
self.remote self.remote
.once('ledger_closed', function (ledger_hash, ledger_index) { .once('ledger_closed', function (mesage) {
// console.log("LEDGER_CLOSED: B: %d: %s", ledger_index, ledger_hash); // console.log("LEDGER_CLOSED: B: %d: %s", ledger_index, ledger_hash);
callback(); callback();
}) })
@@ -198,7 +198,7 @@ buster.testCase("Offer tests", {
function (callback) { function (callback) {
if (!final_create) { if (!final_create) {
self.remote self.remote
.once('ledger_closed', function (ledger_hash, ledger_index) { .once('ledger_closed', function (mesage) {
// console.log("LEDGER_CLOSED: %d: %s", ledger_index, ledger_hash); // console.log("LEDGER_CLOSED: %d: %s", ledger_index, ledger_hash);
}) })
@@ -230,7 +230,7 @@ buster.testCase("Offer tests", {
// See if ledger_accept will crash. // See if ledger_accept will crash.
function (callback) { function (callback) {
self.remote self.remote
.once('ledger_closed', function (ledger_hash, ledger_index) { .once('ledger_closed', function (mesage) {
// console.log("LEDGER_CLOSED: A: %d: %s", ledger_index, ledger_hash); // console.log("LEDGER_CLOSED: A: %d: %s", ledger_index, ledger_hash);
callback(); callback();
}) })
@@ -238,7 +238,7 @@ buster.testCase("Offer tests", {
}, },
function (callback) { function (callback) {
self.remote self.remote
.once('ledger_closed', function (ledger_hash, ledger_index) { .once('ledger_closed', function (mesage) {
// console.log("LEDGER_CLOSED: B: %d: %s", ledger_index, ledger_hash); // console.log("LEDGER_CLOSED: B: %d: %s", ledger_index, ledger_hash);
callback(); callback();
}) })
@@ -309,7 +309,7 @@ buster.testCase("Offer tests", {
// See if ledger_accept will crash. // See if ledger_accept will crash.
function (callback) { function (callback) {
self.remote self.remote
.once('ledger_closed', function (ledger_hash, ledger_index) { .once('ledger_closed', function (mesage) {
// console.log("LEDGER_CLOSED: A: %d: %s", ledger_index, ledger_hash); // console.log("LEDGER_CLOSED: A: %d: %s", ledger_index, ledger_hash);
callback(); callback();
}) })
@@ -317,7 +317,7 @@ buster.testCase("Offer tests", {
}, },
function (callback) { function (callback) {
self.remote self.remote
.once('ledger_closed', function (ledger_hash, ledger_index) { .once('ledger_closed', function (mesage) {
// console.log("LEDGER_CLOSED: B: %d: %s", ledger_index, ledger_hash); // console.log("LEDGER_CLOSED: B: %d: %s", ledger_index, ledger_hash);
callback(); callback();
}) })

View File

@@ -442,7 +442,7 @@ buster.testCase("Sending future", {
// self.what = "Close the ledger and check balance."; // self.what = "Close the ledger and check balance.";
// //
// self.remote // self.remote
// .once('ledger_closed', function (ledger_closed, ledger_closed_index) { // .once('ledger_closed', function (message) {
// // console.log("LEDGER_CLOSED: A: %d: %s", ledger_closed_index, ledger_closed); // // console.log("LEDGER_CLOSED: A: %d: %s", ledger_closed_index, ledger_closed);
// callback(); // callback();
// }) // })