Improve path filtering:

1) Ignore paths with very low liquidity
2) Allow an extra filling path to be added if needed
This commit is contained in:
JoelKatz
2013-11-02 17:40:44 -07:00
parent 3296ac5628
commit 6b2f654a30
4 changed files with 64 additions and 19 deletions

View File

@@ -331,7 +331,8 @@ bool PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
currIssuer.first, currIssuer.second, saDstAmount, valid);
CondLog (!valid, lsINFO, PathRequest) << "PF request not valid";
if (valid && pf.findPaths (iLevel, 4, spsPaths))
STPath extraPath;
if (valid && pf.findPaths (iLevel, 4, spsPaths, extraPath))
{
LedgerEntrySet lesSandbox (cache->getLedger (), tapNONE);
std::vector<PathState::pointer> vpsExpanded;
@@ -343,9 +344,23 @@ bool PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
saMaxAmount.negate ();
WriteLog (lsDEBUG, PathRequest) << "Paths found, calling rippleCalc";
TER terResult = RippleCalc::rippleCalc (lesSandbox, saMaxAmountAct, saDstAmountAct,
vpsExpanded, saMaxAmount, saDstAmount, raDstAccount.getAccountID (), raSrcAccount.getAccountID (),
vpsExpanded, saMaxAmount, saDstAmount,
raDstAccount.getAccountID (), raSrcAccount.getAccountID (),
spsPaths, false, false, false, true);
if ((extraPath.size() > 0) && ((terResult == terNO_LINE) || (terResult == tecPATH_PARTIAL)))
{
WriteLog (lsDEBUG, PathRequest) << "Trying with an extra path element";
spsPaths.addPath(extraPath);
vpsExpanded.clear ();
terResult = RippleCalc::rippleCalc (lesSandbox, saMaxAmountAct, saDstAmountAct,
vpsExpanded, saMaxAmount, saDstAmount,
raDstAccount.getAccountID (), raSrcAccount.getAccountID (),
spsPaths, false, false, false, true);
WriteLog (lsDEBUG, PathRequest) << "Extra path element gives " << transHuman (terResult);
}
if (terResult == tesSUCCESS)
{
Json::Value jvEntry (Json::objectValue);

View File

@@ -126,7 +126,7 @@ Pathfinder::Pathfinder (RippleLineCache::ref cache,
}
bool Pathfinder::findPaths (int iLevel, const unsigned int iMaxPaths, STPathSet& pathsOut)
bool Pathfinder::findPaths (int iLevel, const unsigned int iMaxPaths, STPathSet& pathsOut, STPath& extraPath)
{ // pathsOut contains only non-default paths without source or destiation
// On input, pathsOut contains any paths you want to ensure are included if still good
@@ -221,14 +221,14 @@ bool Pathfinder::findPaths (int iLevel, const unsigned int iMaxPaths, STPathSet&
WriteLog (lsDEBUG, Pathfinder) << mCompletePaths.size() << " paths to filter";
if (mCompletePaths.size() > iMaxPaths)
pathsOut = filterPaths(iMaxPaths);
pathsOut = filterPaths(iMaxPaths, extraPath);
else
pathsOut = mCompletePaths;
return true; // Even if we find no paths, default paths may work, and we don't check them currently
}
STPathSet Pathfinder::filterPaths(int iMaxPaths)
STPathSet Pathfinder::filterPaths(int iMaxPaths, STPath& extraPath)
{
if (mCompletePaths.size() <= iMaxPaths)
return mCompletePaths;
@@ -274,6 +274,9 @@ STPathSet Pathfinder::filterPaths(int iMaxPaths)
std::vector<path_LQ_t> vMap;
// Ignore paths that move only very small amounts
STAmount saMinDstAmount = STAmount::divide(mDstAmount, STAmount(iMaxPaths + 2), mDstAmount);
// Build map of quality to entry.
for (int i = mCompletePaths.size (); i--;)
{
@@ -293,8 +296,8 @@ STPathSet Pathfinder::filterPaths(int iMaxPaths)
terResult = RippleCalc::rippleCalc (
lesSandbox,
saMaxAmountAct,
saDstAmountAct,
saMaxAmountAct, // --> computed input
saDstAmountAct, // --> computed output
vpsExpanded,
mSrcAmount, // --> amount to send max.
mDstAmount, // --> amount to deliver.
@@ -313,7 +316,21 @@ STPathSet Pathfinder::filterPaths(int iMaxPaths)
terResult = tefEXCEPTION;
}
if (tesSUCCESS == terResult)
if (tesSUCCESS != terResult)
{
WriteLog (lsDEBUG, Pathfinder)
<< boost::str (boost::format ("findPaths: dropping: %s: %s")
% transToken (terResult)
% spCurrent.getJson (0));
}
else if (saDstAmountAct < saMinDstAmount)
{
WriteLog (lsDEBUG, Pathfinder)
<< boost::str (boost::format ("findPaths: dropping: outputs %s: %s")
% saDstAmountAct
% spCurrent.getJson (0));
}
else
{
uint64 uQuality = STAmount::getRate (saDstAmountAct, saMaxAmountAct);
@@ -324,13 +341,6 @@ STPathSet Pathfinder::filterPaths(int iMaxPaths)
vMap.push_back (path_LQ_t (uQuality, spCurrent.mPath.size (), saDstAmountAct, i));
}
else
{
WriteLog (lsDEBUG, Pathfinder)
<< boost::str (boost::format ("findPaths: dropping: %s: %s")
% transToken (terResult)
% spCurrent.getJson (0));
}
}
STPathSet spsDst;
@@ -351,6 +361,12 @@ STPathSet Pathfinder::filterPaths(int iMaxPaths)
remaining -= lqt.get<2> ();
spsDst.addPath (mCompletePaths[lqt.get<3> ()]);
}
else if ((iPathsLeft == 0) && (lqt.get<2>() >= mDstAmount) && (extraPath.size() == 0))
{
// found an extra path that can move the whole amount
extraPath = mCompletePaths[lqt.get<3>()];
WriteLog (lsDEBUG, Pathfinder) << "Found extra full path: " << extraPath.getJson(0);
}
else
WriteLog (lsDEBUG, Pathfinder) << "Skipping a non-filling path: " << mCompletePaths[lqt.get<3> ()].getJson (0);
}

View File

@@ -62,7 +62,7 @@ public:
const uint160& srcCurrencyID, const uint160& srcIssuerID, const STAmount& dstAmount, bool& bValid);
static void initPathTable();
bool findPaths (int iLevel, const unsigned int iMaxPaths, STPathSet& spsDst);
bool findPaths (int iLevel, const unsigned int iMaxPaths, STPathSet& spsDst, STPath& spExtraPath);
private:
@@ -102,7 +102,7 @@ private:
void addLink(const STPath& currentPath, STPathSet& incompletePaths, int addFlags);
void addLink(const STPathSet& currentPaths, STPathSet& incompletePaths, int addFlags);
STPathSet& getPaths(const PathType_t& type, bool addComplete = true);
STPathSet filterPaths(int iMaxPaths);
STPathSet filterPaths(int iMaxPaths, STPath& extraPath);
// Our main table of paths

View File

@@ -172,7 +172,8 @@ Json::Value RPCHandler::transactionSign (Json::Value params, bool bSubmit, bool
Pathfinder pf (cache, raSrcAddressID, dstAccountID,
saSendMax.getCurrency (), saSendMax.getIssuer (), saSend, bValid);
if (!bValid || !pf.findPaths (getConfig ().PATH_SEARCH_OLD, 4, spsPaths))
STPath extraPath;
if (!bValid || !pf.findPaths (getConfig ().PATH_SEARCH_OLD, 4, spsPaths, extraPath))
{
WriteLog (lsDEBUG, RPCHandler) << "transactionSign: build_path: No paths found.";
@@ -1560,7 +1561,8 @@ Json::Value RPCHandler::doRipplePathFind (Json::Value params, LoadType* loadType
int level = getConfig().PATH_SEARCH_OLD;
if ((getConfig().PATH_SEARCH_MAX > level) && !getApp().getFeeTrack().isLoadedLocal())
++level;
if (!bValid || !pf.findPaths (level, 4, spsComputed))
STPath extraPath;
if (!bValid || !pf.findPaths (level, 4, spsComputed, extraPath))
{
WriteLog (lsWARNING, RPCHandler) << "ripple_path_find: No paths found.";
}
@@ -1608,6 +1610,18 @@ Json::Value RPCHandler::doRipplePathFind (Json::Value params, LoadType* loadType
% saMaxAmountAct
% saDstAmountAct);
if ((extraPath.size() > 0) && ((terResult == terNO_LINE) || (terResult == tecPATH_PARTIAL)))
{
WriteLog (lsDEBUG, PathRequest) << "Trying with an extra path element";
spsComputed.addPath(extraPath);
vpsExpanded.clear ();
terResult = RippleCalc::rippleCalc (lesSandbox, saMaxAmountAct, saDstAmountAct,
vpsExpanded, saMaxAmount, saDstAmount,
raDst.getAccountID (), raSrc.getAccountID (),
spsComputed, false, false, false, true);
WriteLog (lsDEBUG, PathRequest) << "Extra path element gives " << transHuman (terResult);
}
if (tesSUCCESS == terResult)
{
Json::Value jvEntry (Json::objectValue);