mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user