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:
JoelKatz
2015-02-19 13:32:44 -08:00
committed by Tom Ritchford
parent 84e618b3f2
commit cbeae85731
2 changed files with 45 additions and 8 deletions

View File

@@ -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)

View File

@@ -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;