diff --git a/.gitignore b/.gitignore index 793d90cba5..d9b3fdee92 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,4 @@ node_modules tmp # Ignore database directory. -db/*.db \ No newline at end of file +db/*.db diff --git a/js/remote.js b/js/remote.js index 3c6417fb9c..73c1997055 100644 --- a/js/remote.js +++ b/js/remote.js @@ -14,9 +14,6 @@ // instances of this class for network access. // -// Node -var util = require('util'); - // npm var WebSocket = require('ws'); @@ -78,7 +75,7 @@ Request.prototype.ledger_choose = function (current) { // - ledger_entry // - transaction_entry Request.prototype.ledger_hash = function (h) { - this.message.ledger_hash = n; + this.message.ledger_hash = h; return this; }; @@ -317,7 +314,7 @@ Remote.prototype._connect_start = function () { // with self-signed certs as the user must have pre-approved the self-signed certs. var self = this; - var url = util.format("ws://%s:%s", this.websocket_ip, this.websocket_port); + var url = "ws://" + this.websocket_ip + ":" + this.websocket_port; if (this.trace) console.log("remote: connect: %s", url); @@ -482,7 +479,7 @@ Remote.prototype.request_ledger_hash = function () { var request = new Request(this, 'rpc'); - request.rpc_command = 'ledger_closed'; + request.message.rpc_command = 'ledger_closed'; return request; }; @@ -492,7 +489,7 @@ Remote.prototype.request_ledger_hash = function () { Remote.prototype.request_ledger_current = function () { var request = new Request(this, 'rpc'); - request.rpc_command = 'ledger_current'; + request.message.rpc_command = 'ledger_current'; return request; }; @@ -503,7 +500,9 @@ Remote.prototype.request_ledger_entry = function (type) { assert(this.trusted); // If not trusted, need to check proof, maybe talk packet protocol. var self = this; - var request = new Request(this, 'ledger_entry'); + var request = new Request(this, 'rpc'); + + request.message.rpc_command = 'ledger_entry'; if (type) this.type = type; @@ -559,7 +558,7 @@ Remote.prototype.request_ledger_entry = function (type) { Remote.prototype.request_subscribe = function () { var request = new Request(this, 'subscribe'); - request.message.streams = [ 'ledger' ]; + request.message.streams = [ 'ledger', 'server' ]; return request; }; @@ -567,7 +566,11 @@ Remote.prototype.request_subscribe = function () { Remote.prototype.request_transaction_entry = function (hash) { assert(this.trusted); // If not trusted, need to check proof, maybe talk packet protocol. - return (new Request(this, 'transaction_entry')) + var request = new Request(this, 'rpc'); + + request.message.rpc_command = 'transaction_entry'; + + return request .tx_hash(hash); }; @@ -615,7 +618,9 @@ Remote.prototype.submit = function (transaction) { .request(); } else { - var submit_request = new Request(this, 'submit'); + var submit_request = new Request(this, 'rpc'); + + submit_request.message.rpc_command = 'submit_json'; submit_request.tx_json(transaction.tx_json); submit_request.secret(transaction.secret); @@ -670,7 +675,11 @@ Remote.prototype._server_subscribe = function () { Remote.prototype.ledger_accept = function () { if (this.stand_alone || undefined === this.stand_alone) { - (new Request(this, 'ledger_accept')) + var request = new Request(this, 'rpc'); + + request.message.rpc_command = 'ledger_accept'; + + request .request(); } else { @@ -984,7 +993,7 @@ Transaction.prototype.submit = function () { // XXX make sure self.hash is available. self.remote.request_transaction_entry(self.hash) - .ledger_closed(ledger_hash) + .ledger_hash(ledger_hash) .on('success', function (message) { self.set_state(message.metadata.TransactionResult); self.emit('final', message); diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 5a1ffe1dfd..56faaba9e3 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -1212,8 +1212,10 @@ bool NetworkOPs::unsubLedger(InfoSub* ispListener) } // <-- bool: true=added, false=already there -bool NetworkOPs::subServer(InfoSub* ispListener) +bool NetworkOPs::subServer(InfoSub* ispListener, Json::Value& jvResult) { + jvResult["stand_alone"] = theConfig.RUN_STANDALONE; + return mSubServer.insert(ispListener).second; } diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index 8b356d986d..b7cc79f936 100644 --- a/src/NetworkOPs.h +++ b/src/NetworkOPs.h @@ -228,7 +228,7 @@ public: bool subLedger(InfoSub* ispListener, Json::Value& jvResult); bool unsubLedger(InfoSub* ispListener); - bool subServer(InfoSub* ispListener); + bool subServer(InfoSub* ispListener, Json::Value& jvResult); bool unsubServer(InfoSub* ispListener); bool subTransactions(InfoSub* ispListener); diff --git a/src/RPCHandler.cpp b/src/RPCHandler.cpp index 44863b534a..e1decfb4a2 100644 --- a/src/RPCHandler.cpp +++ b/src/RPCHandler.cpp @@ -326,8 +326,6 @@ Json::Value RPCHandler::doAcceptLedger(const Json::Value ¶ms) return obj; } - - // account_info || // account_info || [] Json::Value RPCHandler::doAccountInfo(const Json::Value ¶ms) @@ -690,9 +688,10 @@ Json::Value RPCHandler::doRippleLinesGet(const Json::Value ¶ms) // submit private_key json Json::Value RPCHandler::doSubmit(const Json::Value& params) { - Json::Value txJSON; - Json::Reader reader; - if(reader.parse(params[1u].asString(),txJSON)) + Json::Value txJSON; + Json::Reader reader; + + if (reader.parse(params[1u].asString(), txJSON)) { Json::Value jvRequest; @@ -702,7 +701,12 @@ Json::Value RPCHandler::doSubmit(const Json::Value& params) return handleJSONSubmit(jvRequest); } - return rpcError(rpcSRC_ACT_MALFORMED); + return rpcError(rpcINVALID_PARAMS); +} + +Json::Value RPCHandler::doSubmitJson(const Json::Value& jvRequest) +{ + return handleJSONSubmit(jvRequest); } @@ -711,9 +715,9 @@ Json::Value RPCHandler::handleJSONSubmit(const Json::Value& jvRequest) Json::Value jvResult; RippleAddress naSeed; RippleAddress srcAddress; - Json::Value txJSON = jvResult["tx_json"]; + Json::Value txJSON = jvRequest["tx_json"]; - if (!naSeed.setSeedGeneric(jvResult["secret"].asString())) + if (!naSeed.setSeedGeneric(jvRequest["secret"].asString())) { return rpcError(rpcBAD_SEED); } @@ -820,7 +824,7 @@ Json::Value RPCHandler::handleJSONSubmit(const Json::Value& jvRequest) RippleAddress naAuthorizedPublic; - RippleAddress naSecret = RippleAddress::createSeedGeneric(jvResult["secret"].asString()); + RippleAddress naSecret = RippleAddress::createSeedGeneric(jvRequest["secret"].asString()); RippleAddress naMasterGenerator = RippleAddress::createGeneratorPublic(naSecret); // Find the index of Account from the master generator, so we can generate the public and private keys. @@ -1288,22 +1292,22 @@ Json::Value RPCHandler::doWalletAccounts(const Json::Value& params) } } - -Json::Value RPCHandler::doLogRotate(const Json::Value& params) +Json::Value RPCHandler::doLogRotate(const Json::Value& params) { return Log::rotateLog(); } -Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& params,int role) +Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& params, int role) { cLog(lsTRACE) << "RPC:" << command; + cLog(lsTRACE) << "RPC params:" << params; static struct { - const char* pCommand; - doFuncPtr dfpFunc; - int iMinParams; - int iMaxParams; - bool mAdminRequired; + const char* pCommand; + doFuncPtr dfpFunc; + int iMinParams; + int iMaxParams; + bool mAdminRequired; unsigned int iOptions; } commandsA[] = { { "accept_ledger", &RPCHandler::doAcceptLedger, 0, 0, true }, @@ -1315,6 +1319,10 @@ Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& param { "data_store", &RPCHandler::doDataStore, 2, 2, true }, { "get_counts", &RPCHandler::doGetCounts, 0, 1, true }, { "ledger", &RPCHandler::doLedger, 0, 2, false, optNetwork }, + { "ledger_accept", &RPCHandler::doLedgerAccept, 0, 0, true, optCurrent }, + { "ledger_closed", &RPCHandler::doLedgerClosed, 0, 0, false, optClosed }, + { "ledger_current", &RPCHandler::doLedgerCurrent, 0, 0, false, optCurrent }, + { "ledger_entry", &RPCHandler::doLedgerEntry, -1, -1, false, optCurrent }, { "log_level", &RPCHandler::doLogLevel, 0, 2, true }, { "logrotate", &RPCHandler::doLogRotate, 0, 0, true }, { "nickname_info", &RPCHandler::doNicknameInfo, 1, 1, false, optCurrent }, @@ -1323,8 +1331,10 @@ Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& param { "profile", &RPCHandler::doProfile, 1, 9, false, optCurrent }, { "ripple_lines_get", &RPCHandler::doRippleLinesGet, 1, 2, false, optCurrent }, { "submit", &RPCHandler::doSubmit, 2, 2, false, optCurrent }, + { "submit_json", &RPCHandler::doSubmitJson, -1, -1, false, optCurrent }, { "server_info", &RPCHandler::doServerInfo, 0, 0, true }, { "stop", &RPCHandler::doStop, 0, 0, true }, + { "transaction_entry", &RPCHandler::doTransactionEntry, -1, -1, false, optCurrent }, { "tx", &RPCHandler::doTx, 1, 1, true }, { "tx_history", &RPCHandler::doTxHistory, 1, 1, false, }, @@ -1359,8 +1369,12 @@ Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& param { return rpcError(rpcNO_PERMISSION); } - else if (params.size() < commandsA[i].iMinParams - || (commandsA[i].iMaxParams >= 0 && params.size() > commandsA[i].iMaxParams)) + else if (commandsA[i].iMinParams >= 0 + ? commandsA[i].iMaxParams + ? (params.size() < commandsA[i].iMinParams + || (commandsA[i].iMaxParams >= 0 && params.size() > commandsA[i].iMaxParams)) + : false + : params.isArray()) { return rpcError(rpcINVALID_PARAMS); } @@ -1605,6 +1619,7 @@ Json::Value RPCHandler::doUnlLoad(const Json::Value& params) Json::Value RPCHandler::doLedgerAccept(const Json::Value& ) { Json::Value jvResult; + if (!theConfig.RUN_STANDALONE) { jvResult["error"] = "notStandAlone"; @@ -1615,16 +1630,13 @@ Json::Value RPCHandler::doLedgerAccept(const Json::Value& ) jvResult["ledger_current_index"] = mNetOps->getCurrentLedgerID(); } - return(jvResult); + + return jvResult; } -Json::Value RPCHandler::doTransactionEntry(const Json::Value& params) +Json::Value RPCHandler::doTransactionEntry(const Json::Value& jvRequest) { Json::Value jvResult; - Json::Value jvRequest; - Json::Reader reader; - if(!reader.parse(params[0u].asString(),jvRequest)) - return rpcError(rpcINVALID_PARAMS); if (!jvRequest.isMember("tx_hash")) { @@ -1672,13 +1684,9 @@ Json::Value RPCHandler::doTransactionEntry(const Json::Value& params) return jvResult; } -Json::Value RPCHandler::doLedgerEntry(const Json::Value& params) +Json::Value RPCHandler::doLedgerEntry(const Json::Value& jvRequest) { Json::Value jvResult; - Json::Value jvRequest; - Json::Reader reader; - if(!reader.parse(params[0u].asString(),jvRequest)) - return rpcError(rpcINVALID_PARAMS); uint256 uLedger = jvRequest.isMember("ledger_hash") ? uint256(jvRequest["ledger_hash"].asString()) : 0; uint32 uLedgerIndex = jvRequest.isMember("ledger_index") && jvRequest["ledger_index"].isNumeric() ? jvRequest["ledger_index"].asUInt() : 0; diff --git a/src/RPCHandler.h b/src/RPCHandler.h index 344bdc2620..ca71d7baca 100644 --- a/src/RPCHandler.h +++ b/src/RPCHandler.h @@ -28,7 +28,7 @@ class RPCHandler Json::Value accountFromString(const uint256& uLedger, RippleAddress& naAccount, bool& bIndex, const std::string& strIdent, const int iIndex); Json::Value doAcceptLedger(const Json::Value ¶ms); - + Json::Value doAccountInfo(const Json::Value& params); Json::Value doAccountTransactions(const Json::Value& params); Json::Value doConnect(const Json::Value& params); @@ -39,21 +39,22 @@ class RPCHandler Json::Value doLedger(const Json::Value& params); Json::Value doLogRotate(const Json::Value& params); Json::Value doNicknameInfo(const Json::Value& params); - + Json::Value doOwnerInfo(const Json::Value& params); - + Json::Value doProfile(const Json::Value& params); Json::Value doPeers(const Json::Value& params); - + Json::Value doRippleLinesGet(const Json::Value ¶ms); Json::Value doServerInfo(const Json::Value& params); Json::Value doSessionClose(const Json::Value& params); Json::Value doSessionOpen(const Json::Value& params); Json::Value doLogLevel(const Json::Value& params); Json::Value doStop(const Json::Value& params); + Json::Value doSubmit(const Json::Value& params); + Json::Value doSubmitJson(const Json::Value& jvRequest); Json::Value doTx(const Json::Value& params); Json::Value doTxHistory(const Json::Value& params); - Json::Value doSubmit(const Json::Value& params); Json::Value doUnlAdd(const Json::Value& params); diff --git a/src/WSConnection.cpp b/src/WSConnection.cpp index ffcdbc0af0..7037836b16 100644 --- a/src/WSConnection.cpp +++ b/src/WSConnection.cpp @@ -65,8 +65,6 @@ Json::Value WSConnection::invokeCommand(Json::Value& jvRequest) Json::Value jvResult(Json::objectValue); - jvResult["type"] = "response"; - if (i < 0) { jvResult["error"] = "unknownCommand"; // Unknown command. @@ -91,6 +89,8 @@ Json::Value WSConnection::invokeCommand(Json::Value& jvRequest) jvResult["result"] = "success"; } + jvResult["type"] = "response"; + return jvResult; } @@ -134,13 +134,13 @@ void WSConnection::doSubscribe(Json::Value& jvResult, Json::Value& jvRequest) { for (Json::Value::iterator it = jvRequest["streams"].begin(); it != jvRequest["streams"].end(); it++) { - if ((*it).isString() ) + if ((*it).isString()) { std::string streamName=(*it).asString(); if(streamName=="server") { - mNetwork.subServer(this); + mNetwork.subServer(this, jvResult); }else if(streamName=="ledger") { mNetwork.subLedger(this, jvResult); @@ -280,14 +280,19 @@ void WSConnection::doRPC(Json::Value& jvResult, Json::Value& jvRequest) { if (jvRequest.isMember("rpc_command") ) { - jvResult=theApp->getRPCHandler().doCommand( + jvResult = theApp->getRPCHandler().doCommand( jvRequest["rpc_command"].asString(), - jvRequest["params"], + jvRequest.isMember("params") + ? jvRequest["params"] + : jvRequest, mHandler->getPublic() ? RPCHandler::GUEST : RPCHandler::ADMIN); - jvResult["type"] = "rpc_response"; - }else jvResult["error"] = "fieldNotCommand"; - + jvResult["type"] = "response"; + } + else + { + jvResult["error"] = "fieldNotCommand"; + } } // XXX Currently requires secret. Allow signed transaction as an alternative. diff --git a/test/remote-test.js b/test/remote-test.js index eec201357f..a085676c5b 100644 --- a/test/remote-test.js +++ b/test/remote-test.js @@ -17,7 +17,7 @@ buster.testCase("Remote functions", { 'setUp' : testutils.build_setup(), 'tearDown' : testutils.build_teardown(), - 'request_ledger_current' : + "request_ledger_current" : function (done) { this.remote.request_ledger_current().on('success', function (m) { // console.log(m); @@ -30,15 +30,16 @@ buster.testCase("Remote functions", { buster.assert(false); }) + .request(); }, - 'request_ledger_closed' : + "request_ledger_hash" : function (done) { - this.remote.request_ledger_closed().on('success', function (m) { + this.remote.request_ledger_hash().on('success', function (m) { // console.log("result: %s", JSON.stringify(m)); - buster.assert.equals(m.ledger_closed_index, 2); + buster.assert.equals(m.ledger_index, 2); done(); }) .on('error', function(m) { @@ -49,16 +50,16 @@ buster.testCase("Remote functions", { .request(); }, - 'manual account_root success' : + "manual account_root success" : function (done) { var self = this; - this.remote.request_ledger_closed().on('success', function (r) { + this.remote.request_ledger_hash().on('success', function (r) { // console.log("result: %s", JSON.stringify(r)); self.remote .request_ledger_entry('account_root') - .ledger_closed(r.ledger_closed) + .ledger_hash(r.ledger_hash) .account_root("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh") .on('success', function (r) { // console.log("account_root: %s", JSON.stringify(r)); @@ -82,16 +83,16 @@ buster.testCase("Remote functions", { }, // XXX This should be detected locally. - 'account_root remote malformedAddress' : + "account_root remote malformedAddress" : function (done) { var self = this; - this.remote.request_ledger_closed().on('success', function (r) { + this.remote.request_ledger_hash().on('success', function (r) { // console.log("result: %s", JSON.stringify(r)); self.remote .request_ledger_entry('account_root') - .ledger_closed(r.ledger_closed) + .ledger_hash(r.ledger_hash) .account_root("zHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh") .on('success', function (r) { // console.log("account_root: %s", JSON.stringify(r)); @@ -115,16 +116,16 @@ buster.testCase("Remote functions", { .request(); }, - 'account_root entryNotFound' : + "account_root entryNotFound" : function (done) { var self = this; - this.remote.request_ledger_closed().on('success', function (r) { + this.remote.request_ledger_hash().on('success', function (r) { // console.log("result: %s", JSON.stringify(r)); self.remote .request_ledger_entry('account_root') - .ledger_closed(r.ledger_closed) + .ledger_hash(r.ledger_hash) .account_root("alice") .on('success', function (r) { // console.log("account_root: %s", JSON.stringify(r)); @@ -147,16 +148,16 @@ buster.testCase("Remote functions", { }).request(); }, - 'ledger_entry index' : + "ledger_entry index" : function (done) { var self = this; - this.remote.request_ledger_closed().on('success', function (r) { + this.remote.request_ledger_hash().on('success', function (r) { // console.log("result: %s", JSON.stringify(r)); self.remote .request_ledger_entry('index') - .ledger_closed(r.ledger_closed) + .ledger_hash(r.ledger_hash) .account_root("alice") .index("2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8") .on('success', function (r) { @@ -180,7 +181,7 @@ buster.testCase("Remote functions", { .request(); }, - 'create account' : + "create account" : function (done) { this.remote.transaction() .payment('root', 'alice', Amount.from_json("10000"))