From 301909fa01ada1e816378edd0d9195e0ffd6e1fd Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Fri, 1 Mar 2013 13:38:37 -0800 Subject: [PATCH] Fix framework for RPC book_offers. --- src/cpp/ripple/CallRPC.cpp | 25 +++++++++++++-------- src/cpp/ripple/NetworkOPs.cpp | 6 +++++ src/cpp/ripple/NetworkOPs.h | 7 +++++- src/cpp/ripple/RPCErr.cpp | 1 + src/cpp/ripple/RPCErr.h | 1 + src/cpp/ripple/RPCHandler.cpp | 41 ++++++++++++++++++++++------------- src/cpp/ripple/main.cpp | 2 +- 7 files changed, 57 insertions(+), 26 deletions(-) diff --git a/src/cpp/ripple/CallRPC.cpp b/src/cpp/ripple/CallRPC.cpp index b84d3ee5b..9f67475f7 100644 --- a/src/cpp/ripple/CallRPC.cpp +++ b/src/cpp/ripple/CallRPC.cpp @@ -209,23 +209,25 @@ Json::Value RPCParser::parseAccountTransactions(const Json::Value& jvParams) return jvRequest; } -// book_offers [ ] +// book_offers [ [ [ []]]] +// limit: 0 = no limit +// proof: 0 or 1 // // Mnemonic: taker puts --> offer --> taker gets Json::Value RPCParser::parseBookOffers(const Json::Value& jvParams) { Json::Value jvRequest(Json::objectValue); - Json::Value jvTakerPuts = jvParseCurrencyIssuer(jvParams[0u].asString()); + Json::Value jvTakerPays = jvParseCurrencyIssuer(jvParams[0u].asString()); Json::Value jvTakerGets = jvParseCurrencyIssuer(jvParams[1u].asString()); - if (isRpcError(jvTakerPuts)) + if (isRpcError(jvTakerPays)) { - return jvTakerPuts; + return jvTakerPays; } else { - jvRequest["taker_puts"] = jvTakerPuts; + jvRequest["taker_pays"] = jvTakerPays; } if (isRpcError(jvTakerGets)) @@ -237,7 +239,7 @@ Json::Value RPCParser::parseBookOffers(const Json::Value& jvParams) jvRequest["taker_gets"] = jvTakerGets; } - if (!jvParseLedger(jvRequest, jvParams[2u].asString())) + if (jvParams.size() >= 3 && !jvParseLedger(jvRequest, jvParams[2u].asString())) return jvRequest; if (jvParams.size() >= 4) @@ -248,8 +250,13 @@ Json::Value RPCParser::parseBookOffers(const Json::Value& jvParams) jvRequest["limit"] = iLimit; } - if (jvParams.size() == 5) - jvRequest["marker"] = jvParams[4u]; + if (jvParams.size() >= 5 && jvParams[4u].asInt()) + { + jvRequest["proof"] = true; + } + + if (jvParams.size() == 6) + jvRequest["marker"] = jvParams[5u]; return jvRequest; } @@ -622,7 +629,7 @@ Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams) { "account_lines", &RPCParser::parseAccountItems, 1, 2 }, { "account_offers", &RPCParser::parseAccountItems, 1, 2 }, { "account_tx", &RPCParser::parseAccountTransactions, 2, 4 }, - { "book_offers", &RPCParser::parseBookOffers, 3, 5 }, + { "book_offers", &RPCParser::parseBookOffers, 2, 6 }, { "connect", &RPCParser::parseConnect, 1, 2 }, { "consensus_info", &RPCParser::parseAsIs, 0, 0 }, { "get_counts", &RPCParser::parseGetCounts, 0, 1 }, diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index 593d9cb7c..8d6f60480 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -1774,5 +1774,11 @@ InfoSub::pointer NetworkOPs::addRpcSub(const std::string& strUrl, InfoSub::ref r return rspEntry; } +void NetworkOPs::getBookPage(Ledger::pointer lpLedger, const uint160& uTakerPaysCurrencyID, const uint160& uTakerPaysIssuerID, const uint160& uTakerGetsCurrencyID, const uint160& uTakerGetsIssuerID, const bool bProof, const unsigned int iLimit, const Json::Value& jvMarker, Json::Value& jvResult) +{ + jvResult["offers"] = Json::Value(Json::arrayValue); +// jvResult["marker"] = Json::Value(Json::arrayValue); +// jvResult["nodes"] = Json::Value(Json::arrayValue); +} // vim:ts=4 diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h index 1dd10c501..1795b41ea 100644 --- a/src/cpp/ripple/NetworkOPs.h +++ b/src/cpp/ripple/NetworkOPs.h @@ -119,7 +119,6 @@ protected: boost::recursive_mutex mMonitorLock; subInfoMapType mSubAccount; subInfoMapType mSubRTAccount; - subRpcMapType mRpcSubMap; @@ -230,6 +229,12 @@ public: Json::Value getOwnerInfo(Ledger::pointer lpLedger, const RippleAddress& naAccount); + // + // Book functions + // + + void getBookPage(Ledger::pointer lpLedger, const uint160& uTakerPaysCurrencyID, const uint160& uTakerPaysIssuerID, const uint160& uTakerGetsCurrencyID, const uint160& uTakerGetsIssuerID, const bool bProof, const unsigned int iLimit, const Json::Value& jvMarker, Json::Value& jvResult); + // raw object operations bool findRawLedger(const uint256& ledgerHash, std::vector& rawLedger); bool findRawTransaction(const uint256& transactionHash, std::vector& rawTransaction); diff --git a/src/cpp/ripple/RPCErr.cpp b/src/cpp/ripple/RPCErr.cpp index 9d1f01259..bf8c7103e 100644 --- a/src/cpp/ripple/RPCErr.cpp +++ b/src/cpp/ripple/RPCErr.cpp @@ -19,6 +19,7 @@ Json::Value rpcError(int iError, Json::Value jvResult) { rpcACT_MALFORMED, "actMalformed", "Account malformed." }, { rpcACT_NOT_FOUND, "actNotFound", "Account not found." }, { rpcBAD_BLOB, "badBlob", "Blob must be a non-empty hex string." }, + { rpcBAD_MARKET, "badMarket", "No such market." }, { rpcBAD_SEED, "badSeed", "Disallowed seed." }, { rpcBAD_SYNTAX, "badSyntax", "Syntax error." }, { rpcCOMMAND_MISSING, "commandMissing", "Missing command entry." }, diff --git a/src/cpp/ripple/RPCErr.h b/src/cpp/ripple/RPCErr.h index 45407969e..e34fef922 100644 --- a/src/cpp/ripple/RPCErr.h +++ b/src/cpp/ripple/RPCErr.h @@ -45,6 +45,7 @@ enum { rpcACT_MALFORMED, rpcQUALITY_MALFORMED, rpcBAD_BLOB, + rpcBAD_MARKET, rpcBAD_SEED, rpcCOMMAND_MISSING, rpcDST_ACT_MALFORMED, diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index 6d6f38801..5189c1515 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -176,7 +176,7 @@ Json::Value RPCHandler::transactionSign(Json::Value jvRequest, bool bSubmit) } Ledger::pointer lSnapshot = boost::make_shared( - boost::ref(*theApp->getOPs().getCurrentLedger()), false); + boost::ref(*mNetOps->getCurrentLedger()), false); { ScopedUnlock su(theApp->getMasterLock()); Pathfinder pf(lSnapshot, raSrcAddressID, dstAccountID, @@ -1060,8 +1060,7 @@ Json::Value RPCHandler::doBookOffers(Json::Value jvRequest) && (!jvTakerPays["issuer"].isString() || !STAmount::issuerFromString(uTakerPaysIssuerID, jvTakerPays["issuer"].asString()))) // Don't allow illegal issuers. - || !uTakerPaysCurrencyID - || !uTakerPaysIssuerID + || (!uTakerPaysCurrencyID != !uTakerPaysIssuerID) || ACCOUNT_ONE == uTakerPaysIssuerID) { cLog(lsINFO) << "Bad taker_pays issuer."; @@ -1071,7 +1070,7 @@ Json::Value RPCHandler::doBookOffers(Json::Value jvRequest) uint160 uTakerGetsCurrencyID; uint160 uTakerGetsIssuerID; - Json::Value jvTakerGets = jvRequest["taker_pays"]; + Json::Value jvTakerGets = jvRequest["taker_gets"]; // Parse mandatory currency. if (!jvTakerGets.isMember("currency") @@ -1086,8 +1085,7 @@ Json::Value RPCHandler::doBookOffers(Json::Value jvRequest) && (!jvTakerGets["issuer"].isString() || !STAmount::issuerFromString(uTakerGetsIssuerID, jvTakerGets["issuer"].asString()))) // Don't allow illegal issuers. - || !uTakerGetsCurrencyID - || !uTakerGetsIssuerID + || (!uTakerGetsCurrencyID != !uTakerGetsIssuerID) || ACCOUNT_ONE == uTakerGetsIssuerID) { cLog(lsINFO) << "Bad taker_gets issuer."; @@ -1095,7 +1093,18 @@ Json::Value RPCHandler::doBookOffers(Json::Value jvRequest) return rpcError(rpcDST_ISR_MALFORMED); } - jvResult["hello"] = "world"; + if (uTakerPaysCurrencyID == uTakerGetsCurrencyID + && uTakerPaysIssuerID == uTakerGetsIssuerID) { + cLog(lsINFO) << "taker_gets same as taker_pays."; + + return rpcError(rpcBAD_MARKET); + } + + const bool bProof = jvRequest.isMember("proof"); + const unsigned int iLimit = jvRequest.isMember("limit") ? jvRequest["limit"].asUInt() : 0; + const Json::Value jvMarker = jvRequest.isMember("marker") ? jvRequest["marker"] : Json::Value(Json::nullValue); + + mNetOps->getBookPage(lpLedger, uTakerPaysCurrencyID, uTakerPaysIssuerID, uTakerGetsCurrencyID, uTakerGetsIssuerID, bProof, iLimit, jvMarker, jvResult); return jvResult; } @@ -1433,7 +1442,7 @@ Json::Value RPCHandler::doConsensusInfo(Json::Value) { Json::Value ret(Json::objectValue); - ret["info"] = theApp->getOPs().getConsensusInfo(); + ret["info"] = mNetOps->getConsensusInfo(); return ret; } @@ -1442,7 +1451,7 @@ Json::Value RPCHandler::doServerInfo(Json::Value) { Json::Value ret(Json::objectValue); - ret["info"] = theApp->getOPs().getServerInfo(true, mRole == ADMIN); + ret["info"] = mNetOps->getServerInfo(true, mRole == ADMIN); return ret; } @@ -1451,7 +1460,7 @@ Json::Value RPCHandler::doServerState(Json::Value) { Json::Value ret(Json::objectValue); - ret["state"] = theApp->getOPs().getServerInfo(false, mRole == ADMIN); + ret["state"] = mNetOps->getServerInfo(false, mRole == ADMIN); return ret; } @@ -1520,7 +1529,7 @@ Json::Value RPCHandler::doTx(Json::Value jvRequest) if (txn->getLedger() != 0) { - Ledger::pointer lgr = theApp->getOPs().getLedgerBySeq(txn->getLedger()); + Ledger::pointer lgr = mNetOps->getLedgerBySeq(txn->getLedger()); if (lgr) { bool okay = false; @@ -1543,7 +1552,7 @@ Json::Value RPCHandler::doTx(Json::Value jvRequest) } } if (okay) - ret["validated"] = theApp->getOPs().isValidated(lgr); + ret["validated"] = mNetOps->isValidated(lgr); } } @@ -1661,7 +1670,7 @@ Json::Value RPCHandler::doAccountTransactions(Json::Value jvRequest) try { #endif - int vl = theApp->getOPs().getValidatedSeq(); + int vl = mNetOps->getValidatedSeq(); ScopedUnlock su(theApp->getMasterLock()); Json::Value ret(Json::objectValue); @@ -1680,7 +1689,7 @@ Json::Value RPCHandler::doAccountTransactions(Json::Value jvRequest) obj["inLedger"] = it->get<2>(); if (it->get<2>() > vl) obj["validated"] = false; - else if (theApp->getOPs().haveLedger(it->get<2>())) + else if (mNetOps->haveLedger(it->get<2>())) obj["validated"] = true; ret["transactions"].append(obj); } @@ -1701,7 +1710,7 @@ Json::Value RPCHandler::doAccountTransactions(Json::Value jvRequest) uint32 s = it->second->getLgrSeq(); if (s > vl) obj["validated"] = false; - else if (theApp->getOPs().haveLedger(s)) + else if (mNetOps->haveLedger(s)) obj["validated"] = true; } @@ -2955,6 +2964,8 @@ Json::Value RPCHandler::doCommand(const Json::Value& jvRequest, int iRole) && mNetOps->getOperatingMode() != NetworkOPs::omTRACKING && mNetOps->getOperatingMode() != NetworkOPs::omFULL) { + cLog(lsINFO) << "Insufficient network mode for RPC: " << mNetOps->strOperatingMode(); + return rpcError(rpcNO_NETWORK); } // XXX Should verify we have a current ledger. diff --git a/src/cpp/ripple/main.cpp b/src/cpp/ripple/main.cpp index 6be4fd138..c3ec7a9a2 100644 --- a/src/cpp/ripple/main.cpp +++ b/src/cpp/ripple/main.cpp @@ -74,7 +74,7 @@ void printHelp(const po::options_description& desc) cerr << " account_lines || []" << endl; cerr << " account_offers || []" << endl; cerr << " account_tx || |( )" << endl; - cerr << " book_offers [ ]" << endl; + cerr << " book_offers [ [ [ []]]]" << endl; cerr << " connect []" << endl; cerr << " consensus_info" << endl; #if ENABLE_INSECURE