diff --git a/src/cpp/ripple/Amount.cpp b/src/cpp/ripple/Amount.cpp index 80027b11e..a799148cc 100644 --- a/src/cpp/ripple/Amount.cpp +++ b/src/cpp/ripple/Amount.cpp @@ -92,8 +92,12 @@ bool STAmount::bSetJson(const Json::Value& jvSource) return true; } - catch (...) + catch (const std::exception& e) { + cLog(lsINFO) + << boost::str(boost::format("bSetJson(): caught: %s") + % e.what()); + return false; } } diff --git a/src/cpp/ripple/Pathfinder.cpp b/src/cpp/ripple/Pathfinder.cpp index 4fd581157..4607079f3 100644 --- a/src/cpp/ripple/Pathfinder.cpp +++ b/src/cpp/ripple/Pathfinder.cpp @@ -4,6 +4,8 @@ #include "Log.h" #include +SETUP_LOG(); + /* JED: V IIII @@ -41,7 +43,7 @@ Test USD to EUR // length of path // width of path // correct currency at the end - +#if 0 bool sortPathOptions(PathOption::pointer first, PathOption::pointer second) { if (first->mTotalCostmTotalCost) return(true); @@ -71,7 +73,7 @@ PathOption::PathOption(PathOption::pointer other) { // TODO: } - +#endif Pathfinder::Pathfinder(RippleAddress& srcAccountID, RippleAddress& dstAccountID, uint160& srcCurrencyID, STAmount dstAmount) : mSrcAccountID(srcAccountID.getAccountID()), mDstAccountID(dstAccountID.getAccountID()), mDstAmount(dstAmount), mSrcCurrencyID(srcCurrencyID), mOrderBook(theApp->getMasterLedger().getCurrentLedger()) @@ -88,7 +90,7 @@ bool Pathfinder::findPaths(int maxSearchSteps, int maxPay, STPathSet& retPathSet std::queue pqueue; STPathElement ele(mSrcAccountID, mSrcCurrencyID, - uint160()); + uint160()); // XXX Might add source issuer. STPath path; path.addElement(ele); // Add the source. @@ -103,11 +105,19 @@ bool Pathfinder::findPaths(int maxSearchSteps, int maxPay, STPathSet& retPathSet ele = path.mPath.back(); // Get the last node from the path. // Determine if path is solved. + + // Done, if dest wants XRP and last element produces XRP. + // Done, if dest wants non-XRP and last element is dest. + + if (!ele.mCurrencyID) { + } if (ele.mAccountID == mDstAccountID) { // Found a path to the destination. if (2 == path.mPath.size()) { // Empty path is default. Drop it. + // XXX Don't drop empty path - we still want an estimate. + cLog(lsDEBUG) << "findPaths: dropping empty path."; continue; } @@ -184,9 +194,10 @@ bool Pathfinder::findPaths(int maxSearchSteps, int maxPay, STPathSet& retPathSet return false; } +#if 0 bool Pathfinder::checkComplete(STPathSet& retPathSet) { - if(mCompletePaths.size()) + if (mCompletePaths.size()) { // TODO: look through these and pick the most promising int count=0; BOOST_FOREACH(PathOption::pointer pathOption,mCompletePaths) @@ -279,4 +290,6 @@ void Pathfinder::addPathOption(PathOption::pointer pathOption) mBuildingPaths.push_back(pathOption); } } +#endif + // vim:ts=4 diff --git a/src/cpp/ripple/Pathfinder.h b/src/cpp/ripple/Pathfinder.h index 6a5fe6987..97f8789b0 100644 --- a/src/cpp/ripple/Pathfinder.h +++ b/src/cpp/ripple/Pathfinder.h @@ -3,34 +3,39 @@ #include "OrderBookDB.h" #include -/* this is a very simple implementation. This can be made way better. -We are simply flooding from the start. And doing an exhaustive search of all paths under maxSearchSteps. An easy improvement would be to flood from both directions -*/ +#if 0 +// +// This is a very simple implementation. This can be made way better. +// We are simply flooding from the start. And doing an exhaustive search of all paths under maxSearchSteps. An easy improvement would +be to flood from both directions. +// + class PathOption { public: typedef boost::shared_ptr pointer; - STPath mPath; - bool mCorrectCurrency; // for the sorting - uint160 mCurrencyID; // what currency we currently have at the end of the path - uint160 mCurrentAccount; // what account is at the end of the path - int mTotalCost; // in send currency - STAmount mMinWidth; // in dest currency - float mQuality; + STPath mPath; + bool mCorrectCurrency; // for the sorting + uint160 mCurrencyID; // what currency we currently have at the end of the path + uint160 mCurrentAccount; // what account is at the end of the path + int mTotalCost; // in send currency + STAmount mMinWidth; // in dest currency + float mQuality; PathOption(uint160& srcAccount,uint160& srcCurrencyID,const uint160& dstCurrencyID); PathOption(PathOption::pointer other); }; +#endif class Pathfinder { - uint160 mSrcAccountID; - uint160 mDstAccountID; - STAmount mDstAmount; - uint160 mSrcCurrencyID; + uint160 mSrcAccountID; + uint160 mDstAccountID; + STAmount mDstAmount; + uint160 mSrcCurrencyID; - OrderBookDB mOrderBook; + OrderBookDB mOrderBook; Ledger::pointer mLedger; std::list mBuildingPaths; diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index 81bafeb6d..26682006e 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -1,3 +1,7 @@ +// +// carries out the RPC +// + #include "Log.h" #include "NetworkOPs.h" #include "RPCHandler.h" @@ -12,14 +16,9 @@ #include "Pathfinder.h" #include #include -/* -carries out the RPC - -*/ SETUP_LOG(); - Json::Value RPCHandler::rpcError(int iError) { static struct { @@ -706,24 +705,36 @@ Json::Value RPCHandler::doRipplePathFind(const Json::Value& jvRequest) // Parse raSrc. !jvRequest.isMember("source_account") || !jvRequest["source_account"].isString() - || !raSrc.setAccountID(jvRequest["source_account"].asString()) - + || !raSrc.setAccountID(jvRequest["source_account"].asString())) + { + cLog(lsINFO) << "Bad source_account."; + jvResult = rpcError(rpcINVALID_PARAMS); + } + else if ( // Parse raDst. - || !jvRequest.isMember("destination_account") + !jvRequest.isMember("destination_account") || !jvRequest["destination_account"].isString() - || !raDst.setAccountID(jvRequest["destination_account"].asString()) - - + || !raDst.setAccountID(jvRequest["destination_account"].asString())) + { + cLog(lsINFO) << "Bad destination_account."; + jvResult = rpcError(rpcINVALID_PARAMS); + } + else if ( // Parse saDst. - || !jvRequest.isMember("destination_amount") - || !saDst.bSetJson("destination_amount") - + !jvRequest.isMember("destination_amount") + || !saDst.bSetJson(jvRequest["destination_amount"])) + { + cLog(lsINFO) << "Bad destination_amount."; + jvResult = rpcError(rpcINVALID_PARAMS); + } + else if ( // Checks on source_currencies. - || !jvRequest.isMember("source_currencies") + !jvRequest.isMember("source_currencies") || !jvRequest["source_currencies"].isArray() - || jvRequest["source_currencies"].size() + || !jvRequest["source_currencies"].size() ) { + cLog(lsINFO) << "Bad source_currencies."; jvResult = rpcError(rpcINVALID_PARAMS); } else @@ -742,10 +753,20 @@ Json::Value RPCHandler::doRipplePathFind(const Json::Value& jvRequest) && (!jvSource["issuer"].isString() || !STAmount::issuerFromString(srcIssuerID, jvSource["issuer"].asString())))) { + cLog(lsINFO) << "Bad currency/issuer."; return rpcError(rpcINVALID_PARAMS); } - // XXX Add some results. + STPathSet spsPaths; + + // XXX Need to add support for srcIssuerID. + Pathfinder pf(raSrc, raDst, srcCurrencyID, saDst); + + if (!spsPaths.isEmpty()) + { + // XXX Also need to check liquidity. + jvSource.append(spsPaths.getJson(0)); + } } jvResult["results"] = jvArray; @@ -1410,7 +1431,7 @@ Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& param { "peers", &RPCHandler::doPeers, 0, 0, true, false, optNone }, { "profile", &RPCHandler::doProfile, 1, 9, false, false, optCurrent }, { "ripple_lines_get", &RPCHandler::doRippleLinesGet, 1, 2, false, false, optCurrent }, - { "path_find", &RPCHandler::doRipplePathFind, -1, -1, false, false, optCurrent }, + { "ripple_path_find", &RPCHandler::doRipplePathFind, -1, -1, false, false, optCurrent }, { "submit", &RPCHandler::doSubmit, 2, 2, false, false, optCurrent }, { "submit_json", &RPCHandler::doSubmitJson, -1, -1, false, false, optCurrent }, { "server_info", &RPCHandler::doServerInfo, 0, 0, true, false, optNone }, diff --git a/src/js/remote.js b/src/js/remote.js index dcc85cb91..313c4b543 100644 --- a/src/js/remote.js +++ b/src/js/remote.js @@ -937,7 +937,29 @@ Remote.prototype.request_ripple_balance = function (account, issuer, currency, c 'account_limit' : accountLimit // Limit set by account with dst as issuer. }); }); -} +}; + +Remote.prototype.request_ripple_path_find = function (src_account, dst_account, dst_amount, source_currencies) { + var self = this; + var request = new Request(this, 'ripple_path_find'); + + request.message.source_account = UInt160.json_rewrite(src_account); + request.message.destination_account = UInt160.json_rewrite(dst_account); + request.message.destination_amount = Amount.json_rewrite(dst_amount); + request.message.source_currencies = source_currencies.map(function (ci) { + var ci_new = {}; + + if ('issuer' in ci) + ci_new.issuer = UInt160.json_rewrite(ci.issuer); + + if ('currency' in ci) + ci_new.currency = Currency.json_rewrite(ci.currency); + + return ci_new; + }); + + return request; +}; Remote.prototype.request_unl_list = function () { return new Request(this, 'unl_list');