mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Fix specified destination issuer in pathfinding (RIPD-812)
* Compute the effective recipient. * Make sure the effective recipient exists. * Prohibit paths to the recipient, if not the effective recipient. * Treat paths to the effective recipient as complete. * Don't find looped paths. * Use the effective recipient for getPathsOut weight.
This commit is contained in:
@@ -175,6 +175,8 @@ Pathfinder::Pathfinder (
|
||||
STAmount const& saDstAmount)
|
||||
: mSrcAccount (uSrcAccount),
|
||||
mDstAccount (uDstAccount),
|
||||
mEffectiveDst (isXRP(saDstAmount.getIssuer ()) ?
|
||||
uDstAccount : saDstAmount.getIssuer ()),
|
||||
mDstAmount (saDstAmount),
|
||||
mSrcCurrency (uSrcCurrency),
|
||||
mSrcIssuer (uSrcIssuer),
|
||||
@@ -193,6 +195,8 @@ Pathfinder::Pathfinder (
|
||||
STAmount const& saDstAmount)
|
||||
: mSrcAccount (uSrcAccount),
|
||||
mDstAccount (uDstAccount),
|
||||
mEffectiveDst (isXRP(saDstAmount.getIssuer ()) ?
|
||||
uDstAccount : saDstAmount.getIssuer ()),
|
||||
mDstAmount (saDstAmount),
|
||||
mSrcCurrency (uSrcCurrency),
|
||||
mSrcAmount (
|
||||
@@ -223,6 +227,7 @@ bool Pathfinder::findPaths (int searchLevel)
|
||||
}
|
||||
|
||||
if (mSrcAccount == mDstAccount &&
|
||||
mDstAccount == mEffectiveDst &&
|
||||
mSrcCurrency == mDstAmount.getCurrency ())
|
||||
{
|
||||
// No need to send to same account with same currency.
|
||||
@@ -231,6 +236,13 @@ bool Pathfinder::findPaths (int searchLevel)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mSrcAccount == mEffectiveDst &&
|
||||
mSrcCurrency == mDstAmount.getCurrency())
|
||||
{
|
||||
// Default path might work, but any path would loop
|
||||
return true;
|
||||
}
|
||||
|
||||
m_loadEvent = getApp ().getJobQueue ().getLoadEvent (
|
||||
jtPATH_FIND, "FindPath");
|
||||
auto currencyIsXRP = isXRP (mSrcCurrency);
|
||||
@@ -266,6 +278,14 @@ bool Pathfinder::findPaths (int searchLevel)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mEffectiveDst != mDstAccount) &&
|
||||
! mLedger->getSLEi (getAccountRootIndex (mEffectiveDst)))
|
||||
{
|
||||
WriteLog (lsDEBUG, Pathfinder)
|
||||
<< "Non-existent gateway";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mLedger->getSLEi (getAccountRootIndex (mDstAccount)))
|
||||
{
|
||||
// Can't find the destination account - we must be funding a new
|
||||
@@ -540,14 +560,12 @@ STPathSet Pathfinder::getBestPaths (
|
||||
mCompletePaths.size() << " paths and " <<
|
||||
extraPaths.size () << " extras";
|
||||
|
||||
if (mCompletePaths.empty() && extraPaths.empty())
|
||||
return mCompletePaths;
|
||||
|
||||
assert (fullLiquidityPath.empty ());
|
||||
const bool issuerIsSender = isXRP (mSrcCurrency) || (srcIssuer == mSrcAccount);
|
||||
|
||||
if (issuerIsSender &&
|
||||
(mCompletePaths.size () <= maxPaths) &&
|
||||
(extraPaths.size() == 0))
|
||||
return mCompletePaths;
|
||||
|
||||
std::vector <PathRank> extraPathRanks;
|
||||
rankPaths (maxPaths, extraPaths, extraPathRanks);
|
||||
|
||||
@@ -877,6 +895,11 @@ void Pathfinder::addLink (
|
||||
auto const& uEndAccount = pathEnd.getAccountID ();
|
||||
bool const bOnXRP = uEndCurrency.isZero ();
|
||||
|
||||
// Does pathfinding really need to get this to
|
||||
// a gateway (the issuer of the destination amount)
|
||||
// rather than the ultimate destination?
|
||||
bool const hasEffectiveDestination = mEffectiveDst != mDstAccount;
|
||||
|
||||
WriteLog (lsTRACE, Pathfinder) << "addLink< flags="
|
||||
<< addFlags << " onXRP=" << bOnXRP;
|
||||
WriteLog (lsTRACE, Pathfinder) << currentPath.getJson (0);
|
||||
@@ -924,7 +947,14 @@ void Pathfinder::addLink (
|
||||
continue;
|
||||
}
|
||||
auto const& acct = rs->getAccountIDPeer ();
|
||||
bool const bToDestination = acct == mDstAccount;
|
||||
|
||||
if (hasEffectiveDestination && (acct == mDstAccount))
|
||||
{
|
||||
// We skipped the gateway
|
||||
continue;
|
||||
}
|
||||
|
||||
bool bToDestination = acct == mEffectiveDst;
|
||||
|
||||
if (bDestOnly && !bToDestination)
|
||||
{
|
||||
@@ -979,7 +1009,7 @@ void Pathfinder::addLink (
|
||||
uEndCurrency,
|
||||
acct,
|
||||
bIsEndCurrency,
|
||||
mDstAccount);
|
||||
mEffectiveDst);
|
||||
if (out)
|
||||
candidates.push_back ({out, acct});
|
||||
}
|
||||
@@ -1108,7 +1138,13 @@ void Pathfinder::addLink (
|
||||
book->getIssuerOut());
|
||||
}
|
||||
|
||||
if (book->getIssuerOut() == mDstAccount &&
|
||||
if (hasEffectiveDestination &&
|
||||
book->getIssuerOut() == mDstAccount &&
|
||||
book->getCurrencyOut() == mDstAmount.getCurrency())
|
||||
{
|
||||
// We skipped a required issuer
|
||||
}
|
||||
else if (book->getIssuerOut() == mEffectiveDst &&
|
||||
book->getCurrencyOut() == mDstAmount.getCurrency())
|
||||
{ // with the destination account, this path is complete
|
||||
WriteLog (lsTRACE, Pathfinder)
|
||||
|
||||
@@ -176,6 +176,7 @@ private:
|
||||
|
||||
Account mSrcAccount;
|
||||
Account mDstAccount;
|
||||
Account mEffectiveDst; // The account the paths need to end at
|
||||
STAmount mDstAmount;
|
||||
Currency mSrcCurrency;
|
||||
boost::optional<Account> mSrcIssuer;
|
||||
|
||||
Reference in New Issue
Block a user