diff --git a/src/ripple/app/paths/Pathfinder.cpp b/src/ripple/app/paths/Pathfinder.cpp index 7966f079a..2950abd85 100644 --- a/src/ripple/app/paths/Pathfinder.cpp +++ b/src/ripple/app/paths/Pathfinder.cpp @@ -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 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) diff --git a/src/ripple/app/paths/Pathfinder.h b/src/ripple/app/paths/Pathfinder.h index f328a6735..4b6a2f346 100644 --- a/src/ripple/app/paths/Pathfinder.h +++ b/src/ripple/app/paths/Pathfinder.h @@ -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 mSrcIssuer;