Compare commits

...

3 Commits

Author SHA1 Message Date
Vinnie Falco
95f31b98a8 Set version to 0.26.4-sp2 2014-11-11 14:22:37 -08:00
Miguel Portilla
10d74ed100 Fix account_lines, account_offers and book_offers result (RIPD-682):
The RPC account_lines and account_offers commands respond with the correct ledger info. account_offers, account_lines and book_offers allow admins unlimited size on the limit param. Specifying a negative value on limit clamps to the minimum value allowed. Incorrect types for limit are correctly reported in the result.
2014-11-11 14:21:49 -08:00
Vinnie Falco
8a7f612d5b Revert pathfinding changes:
* 5e7c527 Revert "Fix account_lines, account_offers and book_offers result (RIPD-682):"
* b3417ca Revert "Fix pathfinding with multiple issuers for one currency (RIPD-618)."
* 00db7f5 Revert "Clean up Pathfinder."
2014-11-11 14:21:40 -08:00
19 changed files with 686 additions and 1321 deletions

View File

@@ -1,5 +1,5 @@
Name: rippled Name: rippled
Version: 0.26.4-sp1 Version: 0.26.4-sp2
Release: 1%{?dist} Release: 1%{?dist}
Summary: Ripple peer-to-peer network daemon Summary: Ripple peer-to-peer network daemon

View File

@@ -24,7 +24,6 @@
#include <ripple/common/RippleSSLContext.h> #include <ripple/common/RippleSSLContext.h>
#include <ripple/app/main/Tuning.h> #include <ripple/app/main/Tuning.h>
#include <ripple/app/misc/ProofOfWorkFactory.h> #include <ripple/app/misc/ProofOfWorkFactory.h>
#include <ripple/app/paths/FindPaths.h>
#include <ripple/core/LoadFeeTrack.h> #include <ripple/core/LoadFeeTrack.h>
#include <ripple/rpc/Manager.h> #include <ripple/rpc/Manager.h>
#include <ripple/nodestore/Database.h> #include <ripple/nodestore/Database.h>
@@ -653,7 +652,7 @@ public:
updateTables (); updateTables ();
m_amendmentTable->addInitial(); m_amendmentTable->addInitial();
initializePathfinding (); Pathfinder::initPathTable ();
m_ledgerMaster->setMinValidations (getConfig ().VALIDATION_QUORUM); m_ledgerMaster->setMinValidations (getConfig ().VALIDATION_QUORUM);

View File

@@ -1,93 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <ripple/app/paths/AccountCurrencies.h>
namespace ripple {
CurrencySet accountSourceCurrencies (
RippleAddress const& raAccountID,
RippleLineCache::ref lrCache,
bool includeXRP)
{
CurrencySet currencies;
// YYY Only bother if they are above reserve
if (includeXRP)
currencies.insert (xrpCurrency());
// List of ripple lines.
auto& rippleLines (lrCache->getRippleLines (raAccountID.getAccountID ()));
for (auto const& item : rippleLines)
{
auto rspEntry = (RippleState*) item.get ();
assert (rspEntry);
if (!rspEntry)
continue;
auto& saBalance = rspEntry->getBalance ();
// Filter out non
if (saBalance > zero
// Have IOUs to send.
|| (rspEntry->getLimitPeer ()
// Peer extends credit.
&& ((-saBalance) < rspEntry->getLimitPeer ()))) // Credit left.
{
currencies.insert (saBalance.getCurrency ());
}
}
currencies.erase (badCurrency());
return currencies;
}
CurrencySet accountDestCurrencies (
RippleAddress const& raAccountID,
RippleLineCache::ref lrCache,
bool includeXRP)
{
CurrencySet currencies;
if (includeXRP)
currencies.insert (xrpCurrency());
// Even if account doesn't exist
// List of ripple lines.
auto& rippleLines (lrCache->getRippleLines (raAccountID.getAccountID ()));
for (auto const& item : rippleLines)
{
auto rspEntry = (RippleState*) item.get ();
assert (rspEntry);
if (!rspEntry)
continue;
auto& saBalance = rspEntry->getBalance ();
if (saBalance < rspEntry->getLimit ()) // Can take more
currencies.insert (saBalance.getCurrency ());
}
currencies.erase (badCurrency());
return currencies;
}
} // ripple

View File

@@ -1,37 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLED_RIPPLE_APP_PATHS_ACCOUNTCURRENCIES_H
#define RIPPLED_RIPPLE_APP_PATHS_ACCOUNTCURRENCIES_H
namespace ripple {
CurrencySet accountDestCurrencies
(RippleAddress const& raAccountID,
RippleLineCache::ref cache,
bool includeXRP);
CurrencySet accountSourceCurrencies
(RippleAddress const& raAccountID,
RippleLineCache::ref lrLedger,
bool includeXRP);
} // ripple
#endif

View File

@@ -1,73 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <ripple/app/paths/Credit.h>
namespace ripple {
STAmount creditLimit (
LedgerEntrySet& ledger,
Account const& account,
Account const& issuer,
Currency const& currency)
{
STAmount result ({currency, account});
auto sleRippleState = ledger.entryCache (ltRIPPLE_STATE,
Ledger::getRippleStateIndex (account, issuer, currency));
if (sleRippleState)
{
result = sleRippleState->getFieldAmount (
account < issuer ? sfLowLimit : sfHighLimit);
result.setIssuer (account);
}
assert (result.getIssuer () == account);
assert (result.getCurrency () == currency);
return result;
}
STAmount creditBalance (
LedgerEntrySet& ledger,
Account const& account,
Account const& issuer,
Currency const& currency)
{
STAmount result ({currency, account});
auto sleRippleState = ledger.entryCache (ltRIPPLE_STATE,
Ledger::getRippleStateIndex (account, issuer, currency));
if (sleRippleState)
{
result = sleRippleState->getFieldAmount (sfBalance);
if (account < issuer)
result.negate ();
result.setIssuer (account);
}
assert (result.getIssuer () == account);
assert (result.getCurrency () == currency);
return result;
}
} // ripple

View File

@@ -1,52 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLED_RIPPLE_APP_PATHS_CREDIT_H
#define RIPPLED_RIPPLE_APP_PATHS_CREDIT_H
namespace ripple {
/** Calculate the maximum amount of IOUs that an account can hold
@param ledger the ledger to check against.
@param account the account of interest.
@param issuer the issuer of the IOU.
@param currency the IOU to check.
@return The maximum amount that can be held.
*/
STAmount creditLimit (
LedgerEntrySet& ledger,
Account const& account,
Account const& issuer,
Currency const& currency);
/** Returns the amount of IOUs issued by issuer that are held by an account
@param ledger the ledger to check against.
@param account the account of interest.
@param issuer the issuer of the IOU.
@param currency the IOU to check.
*/
STAmount creditBalance (
LedgerEntrySet& ledger,
Account const& account,
Account const& issuer,
Currency const& currency);
} // ripple
#endif

View File

@@ -1,141 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <ripple/app/paths/FindPaths.h>
#include <ripple/app/paths/Pathfinder.h>
namespace ripple {
class FindPaths::Impl {
public:
Impl (
RippleLineCache::ref cache,
Account const& srcAccount,
Account const& dstAccount,
STAmount const& dstAmount,
int searchLevel,
unsigned int maxPaths)
: cache_ (cache),
srcAccount_ (srcAccount),
dstAccount_ (dstAccount),
dstAmount_ (dstAmount),
searchLevel_ (searchLevel),
maxPaths_ (maxPaths)
{
}
bool findPathsForIssue (
Issue const& issue,
STPathSet& pathsOut,
STPath& fullLiquidityPath)
{
if (auto& pathfinder = getPathFinder (issue.currency))
{
pathsOut = pathfinder->getBestPaths (
maxPaths_, fullLiquidityPath, issue.account);
return true;
}
return false;
}
private:
hash_map<Currency, std::unique_ptr<Pathfinder>> currencyMap_;
RippleLineCache::ref cache_;
Account const srcAccount_;
Account const dstAccount_;
STAmount const dstAmount_;
int const searchLevel_;
unsigned int const maxPaths_;
std::unique_ptr<Pathfinder> const& getPathFinder (Currency const& currency)
{
auto i = currencyMap_.find (currency);
if (i != currencyMap_.end ())
return i->second;
auto pathfinder = std::make_unique<Pathfinder> (
cache_, srcAccount_, dstAccount_, currency, dstAmount_);
if (pathfinder->findPaths (searchLevel_))
pathfinder->computePathRanks (maxPaths_);
else
pathfinder.reset (); // It's a bad request - clear it.
return currencyMap_[currency] = std::move (pathfinder);
// TODO(tom): why doesn't this faster way compile?
// return currencyMap_.insert (i, std::move (pathfinder)).second;
}
};
FindPaths::FindPaths (
RippleLineCache::ref cache,
Account const& srcAccount,
Account const& dstAccount,
STAmount const& dstAmount,
int level,
unsigned int maxPaths)
: impl_ (std::make_unique<Impl> (
cache, srcAccount, dstAccount, dstAmount, level, maxPaths))
{
}
FindPaths::~FindPaths() = default;
bool FindPaths::findPathsForIssue (
Issue const& issue,
STPathSet& pathsOut,
STPath& fullLiquidityPath)
{
return impl_->findPathsForIssue (issue, pathsOut, fullLiquidityPath);
}
bool findPathsForOneIssuer (
RippleLineCache::ref cache,
Account const& srcAccount,
Account const& dstAccount,
Issue const& srcIssue,
STAmount const& dstAmount,
int searchLevel,
unsigned int const maxPaths,
STPathSet& pathsOut,
STPath& fullLiquidityPath)
{
Pathfinder pf (
cache,
srcAccount,
dstAccount,
srcIssue.currency,
srcIssue.account,
dstAmount);
if (!pf.findPaths (searchLevel))
return false;
pf.addPathsFromPreviousPathfinding (pathsOut);
pf.computePathRanks (maxPaths);
pathsOut = pf.getBestPaths(maxPaths, fullLiquidityPath, srcIssue.account);
return true;
}
void initializePathfinding ()
{
Pathfinder::initPathTable ();
}
} // ripple

View File

@@ -1,93 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLED_RIPPLE_APP_PATHS_FINDPATHS_H
#define RIPPLED_RIPPLE_APP_PATHS_FINDPATHS_H
namespace ripple {
class FindPaths
{
public:
FindPaths (
RippleLineCache::ref cache,
Account const& srcAccount,
Account const& dstAccount,
STAmount const& dstAmount,
/** searchLevel is the maximum search level allowed in an output path.
*/
int searchLevel,
/** maxPaths is the maximum number of paths that can be returned in
pathsOut. */
unsigned int const maxPaths);
~FindPaths();
bool findPathsForIssue (
Issue const& issue,
/** On input, pathsOut contains any paths you want to ensure are
included if still good.
On output, pathsOut will have any additional paths found. Only
non-default paths without source or destination will be added. */
STPathSet& pathsOut,
/** On input, fullLiquidityPath must be an empty STPath.
On output, if fullLiquidityPath is non-empty, it contains one extra
path that can move the entire liquidity requested. */
STPath& fullLiquidityPath);
private:
class Impl;
std::unique_ptr<Impl> impl_;
};
bool findPathsForOneIssuer (
RippleLineCache::ref cache,
Account const& srcAccount,
Account const& dstAccount,
Issue const& srcIssue,
STAmount const& dstAmount,
/** searchLevel is the maximum search level allowed in an output path. */
int searchLevel,
/** maxPaths is the maximum number of paths that can be returned in
pathsOut. */
unsigned int const maxPaths,
/** On input, pathsOut contains any paths you want to ensure are included if
still good.
On output, pathsOut will have any additional paths found. Only
non-default paths without source or destination will be added. */
STPathSet& pathsOut,
/** On input, fullLiquidityPath must be an empty STPath.
On output, if fullLiquidityPath is non-empty, it contains one extra path
that can move the entire liquidity requested. */
STPath& fullLiquidityPath);
void initializePathfinding ();
} // ripple
#endif

View File

@@ -17,20 +17,16 @@
*/ */
//============================================================================== //==============================================================================
#include <ripple/app/paths/AccountCurrencies.h> #include <ripple/types/UintTypes.h>
#include <ripple/app/paths/FindPaths.h>
#include <ripple/core/Config.h> #include <ripple/core/Config.h>
#include <ripple/core/LoadFeeTrack.h> #include <ripple/core/LoadFeeTrack.h>
#include <ripple/types/UintTypes.h>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <tuple> #include <tuple>
namespace ripple { namespace ripple {
PathRequest::PathRequest ( PathRequest::PathRequest (
const std::shared_ptr<InfoSub>& subscriber, const std::shared_ptr<InfoSub>& subscriber, int id, PathRequests& owner,
int id,
PathRequests& owner,
beast::Journal journal) beast::Journal journal)
: m_journal (journal) : m_journal (journal)
, mOwner (owner) , mOwner (owner)
@@ -49,8 +45,7 @@ PathRequest::PathRequest (
} }
static std::string const get_milli_diff ( static std::string const get_milli_diff (
boost::posix_time::ptime const& after, boost::posix_time::ptime const& after, boost::posix_time::ptime
boost::posix_time::ptime
const& before) const& before)
{ {
return beast::lexicalCastThrow <std::string> ( return beast::lexicalCastThrow <std::string> (
@@ -179,7 +174,7 @@ bool PathRequest::isValid (RippleLineCache::ref crCache)
bool const disallowXRP ( bool const disallowXRP (
asDst->peekSLE ().getFlags() & lsfDisallowXRP); asDst->peekSLE ().getFlags() & lsfDisallowXRP);
auto usDestCurrID = accountDestCurrencies ( auto usDestCurrID = usAccountDestCurrencies (
raDstAccount, crCache, !disallowXRP); raDstAccount, crCache, !disallowXRP);
for (auto const& currency : usDestCurrID) for (auto const& currency : usDestCurrID)
@@ -228,16 +223,12 @@ Json::Value PathRequest::doCreate (
{ {
if (bValid) if (bValid)
{ {
m_journal.debug << iIdentifier m_journal.debug << iIdentifier << " valid: " << raSrcAccount.humanAccountID ();
<< " valid: " << raSrcAccount.humanAccountID (); m_journal.debug << iIdentifier << " Deliver: " << saDstAmount.getFullText ();
m_journal.debug << iIdentifier
<< " Deliver: " << saDstAmount.getFullText ();
} }
else else
{
m_journal.debug << iIdentifier << " invalid"; m_journal.debug << iIdentifier << " invalid";
} }
}
valid = bValid; valid = bValid;
return status; return status;
@@ -277,11 +268,9 @@ int PathRequest::parseJson (Json::Value const& jvParams, bool complete)
if (jvParams.isMember ("destination_amount")) if (jvParams.isMember ("destination_amount"))
{ {
if (! amountFromJsonNoThrow ( if (! amountFromJsonNoThrow (saDstAmount, jvParams["destination_amount"]) ||
saDstAmount, jvParams["destination_amount"]) || (saDstAmount.getCurrency ().isZero () && saDstAmount.getIssuer ().isNonZero ()) ||
(saDstAmount.getCurrency ().isZero () && (saDstAmount.getCurrency () == badCurrency()) ||
saDstAmount.getIssuer ().isNonZero ()) ||
(saDstAmount.getCurrency () == badCurrency ()) ||
saDstAmount <= zero) saDstAmount <= zero)
{ {
jvStatus = rpcError (rpcDST_AMT_MALFORMED); jvStatus = rpcError (rpcDST_AMT_MALFORMED);
@@ -331,11 +320,6 @@ int PathRequest::parseJson (Json::Value const& jvParams, bool complete)
return PFR_PJ_INVALID; return PFR_PJ_INVALID;
} }
if (uCur.isNonZero() && uIss.isZero())
{
uIss = raSrcAccount.getAccountID();
}
sciSourceCurrencies.insert ({uCur, uIss}); sciSourceCurrencies.insert ({uCur, uIss});
} }
} }
@@ -379,16 +363,16 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
if (sourceCurrencies.empty ()) if (sourceCurrencies.empty ())
{ {
auto usCurrencies = auto usCurrencies =
accountSourceCurrencies (raSrcAccount, cache, true); usAccountSourceCurrencies (raSrcAccount, cache, true);
bool sameAccount = raSrcAccount == raDstAccount; bool sameAccount = raSrcAccount == raDstAccount;
for (auto const& c: usCurrencies) for (auto const& c: usCurrencies)
{ {
if (!sameAccount || (c != saDstAmount.getCurrency ())) if (!sameAccount || (c != saDstAmount.getCurrency ()))
{ {
if (c.isZero ()) if (c.isZero ())
sourceCurrencies.insert ({c, xrpAccount()}); sourceCurrencies.insert (std::make_pair (c, xrpAccount()));
else else
sourceCurrencies.insert ({c, raSrcAccount.getAccountID ()}); sourceCurrencies.insert (std::make_pair (c, raSrcAccount.getAccountID ()));
} }
} }
} }
@@ -406,30 +390,26 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
bool loaded = getApp().getFeeTrack().isLoadedLocal(); bool loaded = getApp().getFeeTrack().isLoadedLocal();
if (iLevel == 0) if (iLevel == 0)
{ { // first pass
// first pass
if (loaded || fast) if (loaded || fast)
iLevel = getConfig().PATH_SEARCH_FAST; iLevel = getConfig().PATH_SEARCH_FAST;
else else
iLevel = getConfig().PATH_SEARCH; iLevel = getConfig().PATH_SEARCH;
} }
else if ((iLevel == getConfig().PATH_SEARCH_FAST) && !fast) else if ((iLevel == getConfig().PATH_SEARCH_FAST) && !fast)
{ { // leaving fast pathfinding
// leaving fast pathfinding
iLevel = getConfig().PATH_SEARCH; iLevel = getConfig().PATH_SEARCH;
if (loaded && (iLevel > getConfig().PATH_SEARCH_FAST)) if (loaded && (iLevel > getConfig().PATH_SEARCH_FAST))
--iLevel; --iLevel;
} }
else if (bLastSuccess) else if (bLastSuccess)
{ { // decrement, if possible
// decrement, if possible
if (iLevel > getConfig().PATH_SEARCH || if (iLevel > getConfig().PATH_SEARCH ||
(loaded && (iLevel > getConfig().PATH_SEARCH_FAST))) (loaded && (iLevel > getConfig().PATH_SEARCH_FAST)))
--iLevel; --iLevel;
} }
else else
{ { // adjust as needed
// adjust as needed
if (!loaded && (iLevel < getConfig().PATH_SEARCH_MAX)) if (!loaded && (iLevel < getConfig().PATH_SEARCH_MAX))
++iLevel; ++iLevel;
if (loaded && (iLevel > getConfig().PATH_SEARCH_FAST)) if (loaded && (iLevel > getConfig().PATH_SEARCH_FAST))
@@ -440,17 +420,10 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
bool found = false; bool found = false;
FindPaths fp (
cache,
raSrcAccount.getAccountID (),
raDstAccount.getAccountID (),
saDstAmount,
iLevel,
4); // iMaxPaths
for (auto const& currIssuer: sourceCurrencies) for (auto const& currIssuer: sourceCurrencies)
{ {
{ {
STAmount test (currIssuer, 1); STAmount test ({currIssuer.first, currIssuer.second}, 1);
if (m_journal.debug) if (m_journal.debug)
{ {
m_journal.debug m_journal.debug
@@ -458,28 +431,26 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
<< " Trying to find paths: " << test.getFullText (); << " Trying to find paths: " << test.getFullText ();
} }
} }
bool valid;
STPathSet& spsPaths = mContext[currIssuer]; STPathSet& spsPaths = mContext[currIssuer];
STPath fullLiquidityPath; Pathfinder pf (cache, raSrcAccount, raDstAccount,
auto valid = fp.findPathsForIssue ( currIssuer.first, currIssuer.second, saDstAmount, valid);
currIssuer,
spsPaths,
fullLiquidityPath);
CondLog (!valid, lsDEBUG, PathRequest) CondLog (!valid, lsDEBUG, PathRequest)
<< iIdentifier << " PF request not valid"; << iIdentifier << " PF request not valid";
if (valid) STPath extraPath;
if (valid && pf.findPaths (iLevel, 4, spsPaths, extraPath))
{ {
LedgerEntrySet lesSandbox (cache->getLedger (), tapNONE); LedgerEntrySet lesSandbox (cache->getLedger (), tapNONE);
auto& sourceAccount = !isXRP (currIssuer.account) auto& account = currIssuer.second.isNonZero ()
? currIssuer.account ? Account(currIssuer.second)
: isXRP (currIssuer.currency) : isXRP (currIssuer.first)
? xrpAccount() ? xrpAccount()
: raSrcAccount.getAccountID (); : raSrcAccount.getAccountID ();
STAmount saMaxAmount ({currIssuer.currency, sourceAccount}, 1); STAmount saMaxAmount ({currIssuer.first, account}, 1);
saMaxAmount.negate (); saMaxAmount.negate ();
m_journal.debug << iIdentifier m_journal.debug << iIdentifier << " Paths found, calling rippleCalc";
<< " Paths found, calling rippleCalc";
auto rc = path::RippleCalc::rippleCalculate ( auto rc = path::RippleCalc::rippleCalculate (
lesSandbox, lesSandbox,
saMaxAmount, saMaxAmount,
@@ -488,15 +459,13 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
raSrcAccount.getAccountID (), raSrcAccount.getAccountID (),
spsPaths); spsPaths);
if (!fullLiquidityPath.empty() && if (!extraPath.empty() &&
(rc.result () == terNO_LINE || rc.result () == tecPATH_PARTIAL)) (rc.result () == terNO_LINE || rc.result () == tecPATH_PARTIAL))
{ {
m_journal.debug m_journal.debug
<< iIdentifier << " Trying with an extra path element"; << iIdentifier << " Trying with an extra path element";
spsPaths.push_back (fullLiquidityPath); spsPaths.push_back (extraPath);
lesSandbox.clear(); rc = path::RippleCalc::rippleCalculate (lesSandbox,
rc = path::RippleCalc::rippleCalculate (
lesSandbox,
saMaxAmount, saMaxAmount,
saDstAmount, saDstAmount,
raDstAccount.getAccountID (), raDstAccount.getAccountID (),
@@ -515,8 +484,6 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
if (rc.result () == tesSUCCESS) if (rc.result () == tesSUCCESS)
{ {
Json::Value jvEntry (Json::objectValue); Json::Value jvEntry (Json::objectValue);
rc.actualAmountIn.setIssuer (sourceAccount);
jvEntry["source_amount"] = rc.actualAmountIn.getJson (0); jvEntry["source_amount"] = rc.actualAmountIn.getJson (0);
jvEntry["paths_computed"] = spsPaths.getJson (0); jvEntry["paths_computed"] = spsPaths.getJson (0);
found = true; found = true;

View File

@@ -45,13 +45,13 @@ public:
typedef const pointer& ref; typedef const pointer& ref;
typedef const wptr& wref; typedef const wptr& wref;
// TODO(tom): Use Issue instead!
typedef std::pair<Currency, Account> CurrencyIssuer;
public: public:
// VFALCO TODO Break the cyclic dependency on InfoSub // VFALCO TODO Break the cyclic dependency on InfoSub
PathRequest ( PathRequest (std::shared_ptr <InfoSub> const& subscriber,
std::shared_ptr <InfoSub> const& subscriber, int id, PathRequests&, beast::Journal journal);
int id,
PathRequests&,
beast::Journal journal);
~PathRequest (); ~PathRequest ();
@@ -97,8 +97,8 @@ private:
RippleAddress raDstAccount; RippleAddress raDstAccount;
STAmount saDstAmount; STAmount saDstAmount;
std::set<Issue> sciSourceCurrencies; std::set<CurrencyIssuer> sciSourceCurrencies;
std::map<Issue, STPathSet> mContext; std::map<CurrencyIssuer, STPathSet> mContext;
bool bValid; bool bValid;

View File

@@ -17,8 +17,6 @@
*/ */
//============================================================================== //==============================================================================
#include <ripple/app/paths/Credit.h>
namespace ripple { namespace ripple {
// OPTIMIZE: When calculating path increment, note if increment consumes all // OPTIMIZE: When calculating path increment, note if increment consumes all
@@ -316,13 +314,13 @@ TER PathState::pushNode (
if (resultCode == tesSUCCESS) if (resultCode == tesSUCCESS)
{ {
STAmount saOwed = creditBalance (lesEntries, STAmount saOwed = credit_balance (lesEntries,
node.account_, backNode.account_, node.account_, backNode.account_,
node.issue_.currency); node.issue_.currency);
STAmount saLimit; STAmount saLimit;
if (saOwed <= zero) { if (saOwed <= zero) {
saLimit = creditLimit (lesEntries, saLimit = credit_limit (lesEntries,
node.account_, node.account_,
backNode.account_, backNode.account_,
node.issue_.currency); node.issue_.currency);

File diff suppressed because it is too large Load Diff

View File

@@ -31,151 +31,106 @@ namespace ripple {
class Pathfinder class Pathfinder
{ {
public: public:
/** Construct a pathfinder with an issuer.*/
Pathfinder ( Pathfinder (
RippleLineCache::ref cache, RippleLineCache::ref cache,
Account const& srcAccount, RippleAddress const& srcAccountID,
Account const& dstAccount, RippleAddress const& dstAccountID,
Currency const& uSrcCurrency, Currency const& srcCurrencyID,
Account const& uSrcIssuer, Account const& srcIssuerID,
STAmount const& dstAmount); STAmount const& dstAmount,
bool& bValid);
/** Construct a pathfinder without an issuer.*/ static void initPathTable();
Pathfinder (
RippleLineCache::ref cache,
Account const& srcAccount,
Account const& dstAccount,
Currency const& uSrcCurrency,
STAmount const& dstAmount);
~Pathfinder(); bool findPaths (
int iLevel,
unsigned int const iMaxPaths,
STPathSet& spsDst,
STPath& spExtraPath);
static void initPathTable (); private:
bool findPaths (int searchLevel);
/** Make sure that all the input paths are included in mCompletePaths. */
void addPathsFromPreviousPathfinding (STPathSet&);
/** Compute the rankings of the paths. */
void computePathRanks (int maxPaths);
/* Get the best paths, up to maxPaths in number, from mCompletePaths.
On return, if fullLiquidityPath is not empty, then it contains the best
additional single path which can consume all the liquidity.
*/
STPathSet getBestPaths (
int maxPaths,
STPath& fullLiquidityPath,
Account const& srcIssuer);
enum NodeType
{
nt_SOURCE, // The source account: with an issuer account, if needed.
nt_ACCOUNTS, // Accounts that connect from this source/currency.
nt_BOOKS, // Order books that connect to this currency.
nt_XRP_BOOK, // The order book from this currency to XRP.
nt_DEST_BOOK, // The order book to the destination currency/issuer.
nt_DESTINATION // The destination account only.
};
// The PathType is a list of the NodeTypes for a path.
using PathType = std::vector <NodeType>;
// PaymentType represents the types of the source and destination currencies
// in a path request.
enum PaymentType enum PaymentType
{ {
pt_XRP_to_XRP, pt_XRP_to_XRP,
pt_XRP_to_nonXRP, pt_XRP_to_nonXRP,
pt_nonXRP_to_XRP, pt_nonXRP_to_XRP,
pt_nonXRP_to_same, // Destination currency is the same as source. pt_nonXRP_to_same,
pt_nonXRP_to_nonXRP // Destination currency is NOT the same as source. pt_nonXRP_to_nonXRP
}; };
struct PathRank enum NodeType
{ {
std::uint64_t quality; nt_SOURCE, // The source account with an issuer account, if required
std::uint64_t length; nt_ACCOUNTS, // Accounts that connect from this source/currency
STAmount liquidity; nt_BOOKS, // Order books that connect to this currency
int index; nt_XRP_BOOK, // The order book from this currency to XRP
nt_DEST_BOOK, // The order book to the destination currency/issuer
nt_DESTINATION // The destination account only
}; };
private: typedef std::vector<NodeType> PathType_t;
/* typedef std::pair<int, PathType_t> CostedPath_t;
Call graph of Pathfinder methods. typedef std::vector<CostedPath_t> CostedPathList_t;
findPaths: typedef std::pair<int, const char*> PathCost;
addPathsForType: typedef std::vector<PathCost> PathCostList;
addLinks:
addLink:
getPathsOut
issueMatchesOrigin
isNoRippleOut:
isNoRipple
addPathsFromPreviousPathfinding typedef std::map<PaymentType, CostedPathList_t> PathTable;
computePathRanks:
rippleCalculate
getPathLiquidity:
rippleCalculate
getBestPaths
*/
// Add all paths of one type to mCompletePaths. /** Fill a CostedPathList_t from its description. */
STPathSet& addPathsForType (PathType const& type); static void fillPaths(PaymentType type,
PathCostList const& costs);
bool issueMatchesOrigin (Issue const&); /** @return true if any building paths are now complete. */
bool checkComplete (STPathSet& retPathSet);
static std::string pathTypeToString(PathType_t const&);
bool matchesOrigin (Issue const&);
int getPathsOut ( int getPathsOut (
Currency const& currency, Currency const& currency,
Account const& account, Account const& accountID,
bool isDestCurrency, bool isDestCurrency,
Account const& dest); Account const& dest);
void addLink ( void addLink(
STPath const& currentPath, STPath const& currentPath,
STPathSet& incompletePaths, STPathSet& incompletePaths,
int addFlags); int addFlags);
// Call addLink() for each path in currentPaths. void addLink(
void addLinks (
STPathSet const& currentPaths, STPathSet const& currentPaths,
STPathSet& incompletePaths, STPathSet& incompletePaths,
int addFlags); int addFlags);
// Compute the liquidity for a path. Return tesSUCCESS if it has has enough STPathSet& getPaths(PathType_t const& type,
// liquidity to be worth keeping, otherwise an error. bool addComplete = true);
TER getPathLiquidity (
STPath const& path, // IN: The path to check. STPathSet filterPaths(int iMaxPaths,
STAmount const& minDstAmount, // IN: The minimum output this path must STPath& extraPath);
// deliver to be worth keeping.
STAmount& amountOut, // OUT: The actual liquidity on the path. TER checkPath (STPath const& path, STAmount const& minDestAmount,
uint64_t& qualityOut) const; // OUT: The returned initial quality STAmount& amount, uint64_t& quality) const;
// Does this path end on an account-to-account link whose last account has
// set the "no ripple" flag on the link?
bool isNoRippleOut (STPath const& currentPath); bool isNoRippleOut (STPath const& currentPath);
// Is the "no ripple" flag set from one account to another?
bool isNoRipple ( bool isNoRipple (
Account const& fromAccount, Account const& setByID,
Account const& toAccount, Account const& setOnID,
Currency const& currency); Currency const& currencyID);
Account mSrcAccount; // Our main table of paths
Account mDstAccount;
static PathTable mPathTable;
static PathType_t makePath(char const*);
Account mSrcAccountID;
Account mDstAccountID;
STAmount mDstAmount; STAmount mDstAmount;
Currency mSrcCurrency; Currency mSrcCurrencyID;
boost::optional<Account> mSrcIssuer; Account mSrcIssuerID;
STAmount mSrcAmount; STAmount mSrcAmount;
/** The amount remaining from mSrcAccount after the default liquidity has
been removed. */
STAmount mRemainingAmount;
Ledger::pointer mLedger; Ledger::pointer mLedger;
LoadEvent::pointer m_loadEvent; LoadEvent::pointer m_loadEvent;
@@ -183,8 +138,7 @@ private:
STPathElement mSource; STPathElement mSource;
STPathSet mCompletePaths; STPathSet mCompletePaths;
std::vector<PathRank> mPathRanks; std::map<PathType_t, STPathSet> mPaths;
std::map<PathType, STPathSet> mPaths;
hash_map<Issue, int> mPathsOutCountMap; hash_map<Issue, int> mPathsOutCountMap;
@@ -204,6 +158,39 @@ private:
static std::uint32_t const afAC_LAST = 0x080; static std::uint32_t const afAC_LAST = 0x080;
}; };
CurrencySet usAccountDestCurrencies
(RippleAddress const& raAccountID,
RippleLineCache::ref cache,
bool includeXRP);
CurrencySet usAccountSourceCurrencies
(RippleAddress const& raAccountID,
RippleLineCache::ref lrLedger,
bool includeXRP);
/** Calculate the maximum amount of IOUs that an account can hold
@param ledger the ledger to check against.
@param account the account of interest.
@param issuer the issuer of the IOU.
@param currency the IOU to check.
@return The maximum amount that can be held.
*/
STAmount
credit_limit (
LedgerEntrySet& ledger, Account const& account,
Account const& issuer, Currency const& currency);
/** Returns the amount of IOUs issued by issuer that are held by an account
@param ledger the ledger to check against.
@param account the account of interest.
@param issuer the issuer of the IOU.
@param currency the IOU to check.
*/
STAmount
credit_balance (
LedgerEntrySet& ledger, Account const& account,
Account const& issuer, Currency const& currency);
} // ripple } // ripple
#endif #endif

View File

@@ -18,7 +18,6 @@
//============================================================================== //==============================================================================
#include <ripple/app/book/Quality.h> #include <ripple/app/book/Quality.h>
#include <ripple/app/paths/Credit.h>
#include <ripple/app/paths/cursor/RippleLiquidity.h> #include <ripple/app/paths/cursor/RippleLiquidity.h>
namespace ripple { namespace ripple {
@@ -47,8 +46,8 @@ TER PathCursor::reverseLiquidityForAccount () const
auto const isFinalNode = (nodeIndex_ == lastNodeIndex); auto const isFinalNode = (nodeIndex_ == lastNodeIndex);
// 0 quality means none has yet been determined. // 0 quality means none has yet been determined.
std::uint64_t uRateMax = 0 std::uint64_t uRateMax = 0;
;
// Current is allowed to redeem to next. // Current is allowed to redeem to next.
const bool previousNodeIsAccount = !nodeIndex_ || const bool previousNodeIsAccount = !nodeIndex_ ||
previousNode().isAccount(); previousNode().isAccount();
@@ -81,7 +80,7 @@ TER PathCursor::reverseLiquidityForAccount () const
// For previousNodeIsAccount: // For previousNodeIsAccount:
// Previous account is already owed. // Previous account is already owed.
const STAmount saPrvOwed = (previousNodeIsAccount && nodeIndex_ != 0) const STAmount saPrvOwed = (previousNodeIsAccount && nodeIndex_ != 0)
? creditBalance (ledger(), ? credit_balance (ledger(),
node().account_, node().account_,
previousAccountID, previousAccountID,
node().issue_.currency) node().issue_.currency)
@@ -89,7 +88,7 @@ TER PathCursor::reverseLiquidityForAccount () const
// The limit amount that the previous account may owe. // The limit amount that the previous account may owe.
const STAmount saPrvLimit = (previousNodeIsAccount && nodeIndex_ != 0) const STAmount saPrvLimit = (previousNodeIsAccount && nodeIndex_ != 0)
? creditLimit (ledger(), ? credit_limit (ledger(),
node().account_, node().account_,
previousAccountID, previousAccountID,
node().issue_.currency) node().issue_.currency)
@@ -97,7 +96,7 @@ TER PathCursor::reverseLiquidityForAccount () const
// Next account is owed. // Next account is owed.
const STAmount saNxtOwed = (nextNodeIsAccount && nodeIndex_ != lastNodeIndex) const STAmount saNxtOwed = (nextNodeIsAccount && nodeIndex_ != lastNodeIndex)
? creditBalance (ledger(), ? credit_balance (ledger(),
node().account_, node().account_,
nextAccountID, nextAccountID,
node().issue_.currency) node().issue_.currency)

View File

@@ -33,7 +33,7 @@ char const* getRawVersionString ()
// //
// The build version number (edit this for each release) // The build version number (edit this for each release)
// //
"0.26.4-sp1" "0.26.4-sp2"
// //
// Must follow the format described here: // Must follow the format described here:
// //

View File

@@ -17,8 +17,6 @@
*/ */
//============================================================================== //==============================================================================
#include <ripple/app/paths/AccountCurrencies.h>
#include <ripple/app/paths/FindPaths.h>
#include <ripple/rpc/impl/LegacyPathFind.h> #include <ripple/rpc/impl/LegacyPathFind.h>
namespace ripple { namespace ripple {
@@ -121,10 +119,11 @@ Json::Value doRipplePathFind (RPC::Context& context)
} }
else else
{ {
auto currencies = accountSourceCurrencies (raSrc, cache, true); auto usCurrencies = usAccountSourceCurrencies (raSrc, cache, true);
jvSrcCurrencies = Json::Value (Json::arrayValue); jvSrcCurrencies = Json::Value (Json::arrayValue);
for (auto const& uCurrency: currencies) for (auto const& uCurrency: usCurrencies)
{ {
Json::Value jvCurrency (Json::objectValue); Json::Value jvCurrency (Json::objectValue);
jvCurrency["currency"] = to_string(uCurrency); jvCurrency["currency"] = to_string(uCurrency);
@@ -135,9 +134,7 @@ Json::Value doRipplePathFind (RPC::Context& context)
// Fill in currencies destination will accept // Fill in currencies destination will accept
Json::Value jvDestCur (Json::arrayValue); Json::Value jvDestCur (Json::arrayValue);
// TODO(tom): this could be optimized the same way that auto usDestCurrID = usAccountDestCurrencies (raDst, cache, true);
// PathRequest::doUpdate() is - if we don't obsolete this code first.
auto usDestCurrID = accountDestCurrencies (raDst, cache, true);
for (auto const& uCurrency: usDestCurrID) for (auto const& uCurrency: usDestCurrID)
jvDestCur.append (to_string (uCurrency)); jvDestCur.append (to_string (uCurrency));
@@ -146,29 +143,6 @@ Json::Value doRipplePathFind (RPC::Context& context)
Json::Value jvArray (Json::arrayValue); Json::Value jvArray (Json::arrayValue);
int level = getConfig().PATH_SEARCH_OLD;
if ((getConfig().PATH_SEARCH_MAX > level)
&& !getApp().getFeeTrack().isLoadedLocal())
{
++level;
}
if (context.params_.isMember("depth")
&& context.params_["depth"].isIntegral())
{
int rLev = context.params_["search_depth"].asInt ();
if ((rLev < level) || (context.role_ == Config::ADMIN))
level = rLev;
}
FindPaths fp (
cache,
raSrc.getAccountID(),
raDst.getAccountID(),
saDstAmount,
level,
4); // max paths
for (unsigned int i = 0; i != jvSrcCurrencies.size (); ++i) for (unsigned int i = 0; i != jvSrcCurrencies.size (); ++i)
{ {
Json::Value jvSource = jvSrcCurrencies[i]; Json::Value jvSource = jvSrcCurrencies[i];
@@ -203,6 +177,11 @@ Json::Value doRipplePathFind (RPC::Context& context)
return rpcError (rpcSRC_ISR_MALFORMED); return rpcError (rpcSRC_ISR_MALFORMED);
} }
STPathSet spsComputed;
bool bValid;
Pathfinder pf (cache, raSrc, raDst, uSrcCurrencyID,
uSrcIssuerID, saDstAmount, bValid);
int level = getConfig().PATH_SEARCH_OLD; int level = getConfig().PATH_SEARCH_OLD;
if ((getConfig().PATH_SEARCH_MAX > level) if ((getConfig().PATH_SEARCH_MAX > level)
&& !getApp().getFeeTrack().isLoadedLocal()) && !getApp().getFeeTrack().isLoadedLocal())
@@ -217,7 +196,6 @@ Json::Value doRipplePathFind (RPC::Context& context)
level = rLev; level = rLev;
} }
STPathSet spsComputed;
if (context.params_.isMember("paths")) if (context.params_.isMember("paths"))
{ {
STParsedJSONObject paths ("paths", context.params_["paths"]); STParsedJSONObject paths ("paths", context.params_["paths"]);
@@ -227,12 +205,8 @@ Json::Value doRipplePathFind (RPC::Context& context)
spsComputed = paths.object.get()->downcast<STPathSet> (); spsComputed = paths.object.get()->downcast<STPathSet> ();
} }
STPath fullLiquidityPath; STPath extraPath;
auto valid = fp.findPathsForIssue ( if (!bValid || !pf.findPaths (level, 4, spsComputed, extraPath))
{uSrcCurrencyID, uSrcIssuerID},
spsComputed,
fullLiquidityPath);
if (!valid)
{ {
WriteLog (lsWARNING, RPCHandler) WriteLog (lsWARNING, RPCHandler)
<< "ripple_path_find: No paths found."; << "ripple_path_find: No paths found.";
@@ -267,13 +241,13 @@ Json::Value doRipplePathFind (RPC::Context& context)
<< " saMaxAmountAct=" << rc.actualAmountIn << " saMaxAmountAct=" << rc.actualAmountIn
<< " saDstAmountAct=" << rc.actualAmountOut; << " saDstAmountAct=" << rc.actualAmountOut;
if (fullLiquidityPath.size() > 0 && if (extraPath.size() > 0 &&
(rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL)) (rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL))
{ {
WriteLog (lsDEBUG, PathRequest) WriteLog (lsDEBUG, PathRequest)
<< "Trying with an extra path element"; << "Trying with an extra path element";
spsComputed.push_back (fullLiquidityPath); spsComputed.push_back (extraPath);
lesSandbox.clear (); lesSandbox.clear ();
rc = path::RippleCalc::rippleCalculate ( rc = path::RippleCalc::rippleCalculate (
lesSandbox, lesSandbox,

View File

@@ -17,7 +17,6 @@
*/ */
//============================================================================== //==============================================================================
#include <ripple/app/paths/FindPaths.h>
#include <ripple/basics/StringUtilities.h> #include <ripple/basics/StringUtilities.h>
#include <ripple/rpc/impl/TransactionSign.h> #include <ripple/rpc/impl/TransactionSign.h>
#include <beast/unit_test.h> #include <beast/unit_test.h>
@@ -126,6 +125,7 @@ static Json::Value signPayment(
&& params.isMember ("build_path")) && params.isMember ("build_path"))
{ {
// Need a ripple path. // Need a ripple path.
STPathSet spsPaths;
Currency uSrcCurrencyID; Currency uSrcCurrencyID;
Account uSrcIssuerID; Account uSrcIssuerID;
@@ -152,21 +152,22 @@ static Json::Value signPayment(
if (!lpf.isOk ()) if (!lpf.isOk ())
return rpcError (rpcTOO_BUSY); return rpcError (rpcTOO_BUSY);
bool bValid;
auto cache = std::make_shared<RippleLineCache> (lSnapshot); auto cache = std::make_shared<RippleLineCache> (lSnapshot);
STPathSet spsPaths; Pathfinder pf (
STPath fullLiquidityPath;
auto valid = findPathsForOneIssuer (
cache, cache,
raSrcAddressID.getAccountID(), raSrcAddressID,
dstAccountID.getAccountID(), dstAccountID,
saSendMax.issue (), saSendMax.getCurrency (),
amount, saSendMax.getIssuer (),
getConfig ().PATH_SEARCH_OLD, amount, bValid);
4, // iMaxPaths
spsPaths,
fullLiquidityPath);
if (!valid) STPath extraPath;
if (!bValid ||
!pf.findPaths (getConfig ().PATH_SEARCH_OLD,
4,
spsPaths,
extraPath))
{ {
WriteLog (lsDEBUG, RPCHandler) WriteLog (lsDEBUG, RPCHandler)
<< "transactionSign: build_path: No paths found."; << "transactionSign: build_path: No paths found.";

View File

@@ -117,5 +117,7 @@
#include <ripple/app/main/ParameterTable.h> #include <ripple/app/main/ParameterTable.h>
#include <ripple/app/paths/PathState.h> #include <ripple/app/paths/PathState.h>
#include <ripple/app/paths/RippleCalc.h> #include <ripple/app/paths/RippleCalc.h>
#include <ripple/app/paths/Pathfinder.h>
#endif #endif

View File

@@ -29,8 +29,5 @@
#include <ripple/app/ledger/OrderBookIterator.cpp> #include <ripple/app/ledger/OrderBookIterator.cpp>
#include <ripple/app/consensus/DisputedTx.cpp> #include <ripple/app/consensus/DisputedTx.cpp>
#include <ripple/app/misc/HashRouter.cpp> #include <ripple/app/misc/HashRouter.cpp>
#include <ripple/app/paths/AccountCurrencies.cpp>
#include <ripple/app/paths/Credit.cpp>
#include <ripple/app/paths/FindPaths.cpp>
#include <ripple/app/paths/Pathfinder.cpp> #include <ripple/app/paths/Pathfinder.cpp>
#include <ripple/app/misc/AmendmentTableImpl.cpp> #include <ripple/app/misc/AmendmentTableImpl.cpp>