Work toward ripple_path_find.

This commit is contained in:
Arthur Britto
2012-11-22 11:51:40 -08:00
parent 814be24361
commit 4e713c58ad
5 changed files with 104 additions and 39 deletions

View File

@@ -92,8 +92,12 @@ bool STAmount::bSetJson(const Json::Value& jvSource)
return true; return true;
} }
catch (...) catch (const std::exception& e)
{ {
cLog(lsINFO)
<< boost::str(boost::format("bSetJson(): caught: %s")
% e.what());
return false; return false;
} }
} }

View File

@@ -4,6 +4,8 @@
#include "Log.h" #include "Log.h"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
SETUP_LOG();
/* /*
JED: V IIII JED: V IIII
@@ -41,7 +43,7 @@ Test USD to EUR
// length of path // length of path
// width of path // width of path
// correct currency at the end // correct currency at the end
#if 0
bool sortPathOptions(PathOption::pointer first, PathOption::pointer second) bool sortPathOptions(PathOption::pointer first, PathOption::pointer second)
{ {
if (first->mTotalCost<second->mTotalCost) return(true); if (first->mTotalCost<second->mTotalCost) return(true);
@@ -71,7 +73,7 @@ PathOption::PathOption(PathOption::pointer other)
{ {
// TODO: // TODO:
} }
#endif
Pathfinder::Pathfinder(RippleAddress& srcAccountID, RippleAddress& dstAccountID, uint160& srcCurrencyID, STAmount dstAmount) : Pathfinder::Pathfinder(RippleAddress& srcAccountID, RippleAddress& dstAccountID, uint160& srcCurrencyID, STAmount dstAmount) :
mSrcAccountID(srcAccountID.getAccountID()), mDstAccountID(dstAccountID.getAccountID()), mDstAmount(dstAmount), mSrcCurrencyID(srcCurrencyID), mOrderBook(theApp->getMasterLedger().getCurrentLedger()) 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<STPath> pqueue; std::queue<STPath> pqueue;
STPathElement ele(mSrcAccountID, STPathElement ele(mSrcAccountID,
mSrcCurrencyID, mSrcCurrencyID,
uint160()); uint160()); // XXX Might add source issuer.
STPath path; STPath path;
path.addElement(ele); // Add the source. 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. ele = path.mPath.back(); // Get the last node from the path.
// Determine if path is solved. // 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) { if (ele.mAccountID == mDstAccountID) {
// Found a path to the destination. // Found a path to the destination.
if (2 == path.mPath.size()) { if (2 == path.mPath.size()) {
// Empty path is default. Drop it. // Empty path is default. Drop it.
// XXX Don't drop empty path - we still want an estimate.
cLog(lsDEBUG) << "findPaths: dropping empty path.";
continue; continue;
} }
@@ -184,9 +194,10 @@ bool Pathfinder::findPaths(int maxSearchSteps, int maxPay, STPathSet& retPathSet
return false; return false;
} }
#if 0
bool Pathfinder::checkComplete(STPathSet& retPathSet) bool Pathfinder::checkComplete(STPathSet& retPathSet)
{ {
if(mCompletePaths.size()) if (mCompletePaths.size())
{ // TODO: look through these and pick the most promising { // TODO: look through these and pick the most promising
int count=0; int count=0;
BOOST_FOREACH(PathOption::pointer pathOption,mCompletePaths) BOOST_FOREACH(PathOption::pointer pathOption,mCompletePaths)
@@ -279,4 +290,6 @@ void Pathfinder::addPathOption(PathOption::pointer pathOption)
mBuildingPaths.push_back(pathOption); mBuildingPaths.push_back(pathOption);
} }
} }
#endif
// vim:ts=4 // vim:ts=4

View File

@@ -3,9 +3,13 @@
#include "OrderBookDB.h" #include "OrderBookDB.h"
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
/* this is a very simple implementation. This can be made way better. #if 0
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 //
*/ // 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 class PathOption
{ {
public: public:
@@ -22,6 +26,7 @@ public:
PathOption(uint160& srcAccount,uint160& srcCurrencyID,const uint160& dstCurrencyID); PathOption(uint160& srcAccount,uint160& srcCurrencyID,const uint160& dstCurrencyID);
PathOption(PathOption::pointer other); PathOption(PathOption::pointer other);
}; };
#endif
class Pathfinder class Pathfinder
{ {

View File

@@ -1,3 +1,7 @@
//
// carries out the RPC
//
#include "Log.h" #include "Log.h"
#include "NetworkOPs.h" #include "NetworkOPs.h"
#include "RPCHandler.h" #include "RPCHandler.h"
@@ -12,14 +16,9 @@
#include "Pathfinder.h" #include "Pathfinder.h"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <openssl/md5.h> #include <openssl/md5.h>
/*
carries out the RPC
*/
SETUP_LOG(); SETUP_LOG();
Json::Value RPCHandler::rpcError(int iError) Json::Value RPCHandler::rpcError(int iError)
{ {
static struct { static struct {
@@ -706,24 +705,36 @@ Json::Value RPCHandler::doRipplePathFind(const Json::Value& jvRequest)
// Parse raSrc. // Parse raSrc.
!jvRequest.isMember("source_account") !jvRequest.isMember("source_account")
|| !jvRequest["source_account"].isString() || !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. // Parse raDst.
|| !jvRequest.isMember("destination_account") !jvRequest.isMember("destination_account")
|| !jvRequest["destination_account"].isString() || !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. // Parse saDst.
|| !jvRequest.isMember("destination_amount") !jvRequest.isMember("destination_amount")
|| !saDst.bSetJson("destination_amount") || !saDst.bSetJson(jvRequest["destination_amount"]))
{
cLog(lsINFO) << "Bad destination_amount.";
jvResult = rpcError(rpcINVALID_PARAMS);
}
else if (
// Checks on source_currencies. // Checks on source_currencies.
|| !jvRequest.isMember("source_currencies") !jvRequest.isMember("source_currencies")
|| !jvRequest["source_currencies"].isArray() || !jvRequest["source_currencies"].isArray()
|| jvRequest["source_currencies"].size() || !jvRequest["source_currencies"].size()
) )
{ {
cLog(lsINFO) << "Bad source_currencies.";
jvResult = rpcError(rpcINVALID_PARAMS); jvResult = rpcError(rpcINVALID_PARAMS);
} }
else else
@@ -742,10 +753,20 @@ Json::Value RPCHandler::doRipplePathFind(const Json::Value& jvRequest)
&& (!jvSource["issuer"].isString() && (!jvSource["issuer"].isString()
|| !STAmount::issuerFromString(srcIssuerID, jvSource["issuer"].asString())))) || !STAmount::issuerFromString(srcIssuerID, jvSource["issuer"].asString()))))
{ {
cLog(lsINFO) << "Bad currency/issuer.";
return rpcError(rpcINVALID_PARAMS); 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; 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 }, { "peers", &RPCHandler::doPeers, 0, 0, true, false, optNone },
{ "profile", &RPCHandler::doProfile, 1, 9, false, false, optCurrent }, { "profile", &RPCHandler::doProfile, 1, 9, false, false, optCurrent },
{ "ripple_lines_get", &RPCHandler::doRippleLinesGet, 1, 2, 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", &RPCHandler::doSubmit, 2, 2, false, false, optCurrent },
{ "submit_json", &RPCHandler::doSubmitJson, -1, -1, false, false, optCurrent }, { "submit_json", &RPCHandler::doSubmitJson, -1, -1, false, false, optCurrent },
{ "server_info", &RPCHandler::doServerInfo, 0, 0, true, false, optNone }, { "server_info", &RPCHandler::doServerInfo, 0, 0, true, false, optNone },

View File

@@ -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. '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 () { Remote.prototype.request_unl_list = function () {
return new Request(this, 'unl_list'); return new Request(this, 'unl_list');