mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Clean up Pathfinder.
* Restrict to 80-columns and other style cleanups. * Make pathfinding a free function and hide the class Pathfinder. * Split off unrelated utility functions into separate files.
This commit is contained in:
@@ -24,6 +24,7 @@
|
|||||||
#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>
|
||||||
@@ -652,7 +653,7 @@ public:
|
|||||||
updateTables ();
|
updateTables ();
|
||||||
|
|
||||||
m_amendmentTable->addInitial();
|
m_amendmentTable->addInitial();
|
||||||
Pathfinder::initPathTable ();
|
initializePathfinding ();
|
||||||
|
|
||||||
m_ledgerMaster->setMinValidations (getConfig ().VALIDATION_QUORUM);
|
m_ledgerMaster->setMinValidations (getConfig ().VALIDATION_QUORUM);
|
||||||
|
|
||||||
|
|||||||
93
src/ripple/app/paths/AccountCurrencies.cpp
Normal file
93
src/ripple/app/paths/AccountCurrencies.cpp
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
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
|
||||||
37
src/ripple/app/paths/AccountCurrencies.h
Normal file
37
src/ripple/app/paths/AccountCurrencies.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
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
|
||||||
73
src/ripple/app/paths/Credit.cpp
Normal file
73
src/ripple/app/paths/Credit.cpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
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
|
||||||
52
src/ripple/app/paths/Credit.h
Normal file
52
src/ripple/app/paths/Credit.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
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
|
||||||
58
src/ripple/app/paths/FindPaths.cpp
Normal file
58
src/ripple/app/paths/FindPaths.cpp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
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 {
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Yes, ensurePathsAreComplete is called BEFORE we compute the paths...
|
||||||
|
pf.ensurePathsAreComplete (pathsOut);
|
||||||
|
pathsOut = pf.getBestPaths(maxPaths, fullLiquidityPath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializePathfinding ()
|
||||||
|
{
|
||||||
|
Pathfinder::initPathTable ();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // ripple
|
||||||
56
src/ripple/app/paths/FindPaths.h
Normal file
56
src/ripple/app/paths/FindPaths.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
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 {
|
||||||
|
|
||||||
|
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
|
||||||
@@ -17,27 +17,31 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <ripple/types/UintTypes.h>
|
#include <ripple/app/paths/AccountCurrencies.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, int id, PathRequests& owner,
|
const std::shared_ptr<InfoSub>& subscriber,
|
||||||
|
int id,
|
||||||
|
PathRequests& owner,
|
||||||
beast::Journal journal)
|
beast::Journal journal)
|
||||||
: m_journal (journal)
|
: m_journal (journal)
|
||||||
, mOwner (owner)
|
, mOwner (owner)
|
||||||
, wpSubscriber (subscriber)
|
, wpSubscriber (subscriber)
|
||||||
, jvStatus (Json::objectValue)
|
, jvStatus (Json::objectValue)
|
||||||
, bValid (false)
|
, bValid (false)
|
||||||
, mLastIndex (0)
|
, mLastIndex (0)
|
||||||
, mInProgress (false)
|
, mInProgress (false)
|
||||||
, iLastLevel (0)
|
, iLastLevel (0)
|
||||||
, bLastSuccess (false)
|
, bLastSuccess (false)
|
||||||
, iIdentifier (id)
|
, iIdentifier (id)
|
||||||
{
|
{
|
||||||
if (m_journal.debug)
|
if (m_journal.debug)
|
||||||
m_journal.debug << iIdentifier << " created";
|
m_journal.debug << iIdentifier << " created";
|
||||||
@@ -45,7 +49,8 @@ const std::shared_ptr<InfoSub>& subscriber, int id, PathRequests& owner,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static std::string const get_milli_diff (
|
static std::string const get_milli_diff (
|
||||||
boost::posix_time::ptime const& after, boost::posix_time::ptime
|
boost::posix_time::ptime const& after,
|
||||||
|
boost::posix_time::ptime
|
||||||
const& before)
|
const& before)
|
||||||
{
|
{
|
||||||
return beast::lexicalCastThrow <std::string> (
|
return beast::lexicalCastThrow <std::string> (
|
||||||
@@ -174,7 +179,7 @@ bool PathRequest::isValid (RippleLineCache::ref crCache)
|
|||||||
bool const disallowXRP (
|
bool const disallowXRP (
|
||||||
asDst->peekSLE ().getFlags() & lsfDisallowXRP);
|
asDst->peekSLE ().getFlags() & lsfDisallowXRP);
|
||||||
|
|
||||||
auto usDestCurrID = usAccountDestCurrencies (
|
auto usDestCurrID = accountDestCurrencies (
|
||||||
raDstAccount, crCache, !disallowXRP);
|
raDstAccount, crCache, !disallowXRP);
|
||||||
|
|
||||||
for (auto const& currency : usDestCurrID)
|
for (auto const& currency : usDestCurrID)
|
||||||
@@ -223,11 +228,15 @@ Json::Value PathRequest::doCreate (
|
|||||||
{
|
{
|
||||||
if (bValid)
|
if (bValid)
|
||||||
{
|
{
|
||||||
m_journal.debug << iIdentifier << " valid: " << raSrcAccount.humanAccountID ();
|
m_journal.debug << iIdentifier
|
||||||
m_journal.debug << iIdentifier << " Deliver: " << saDstAmount.getFullText ();
|
<< " valid: " << raSrcAccount.humanAccountID ();
|
||||||
|
m_journal.debug << iIdentifier
|
||||||
|
<< " Deliver: " << saDstAmount.getFullText ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
m_journal.debug << iIdentifier << " invalid";
|
m_journal.debug << iIdentifier << " invalid";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
valid = bValid;
|
valid = bValid;
|
||||||
@@ -268,10 +277,12 @@ int PathRequest::parseJson (Json::Value const& jvParams, bool complete)
|
|||||||
|
|
||||||
if (jvParams.isMember ("destination_amount"))
|
if (jvParams.isMember ("destination_amount"))
|
||||||
{
|
{
|
||||||
if (! amountFromJsonNoThrow (saDstAmount, jvParams["destination_amount"]) ||
|
if (! amountFromJsonNoThrow (
|
||||||
(saDstAmount.getCurrency ().isZero () && saDstAmount.getIssuer ().isNonZero ()) ||
|
saDstAmount, jvParams["destination_amount"]) ||
|
||||||
(saDstAmount.getCurrency () == badCurrency()) ||
|
(saDstAmount.getCurrency ().isZero () &&
|
||||||
saDstAmount <= zero)
|
saDstAmount.getIssuer ().isNonZero ()) ||
|
||||||
|
(saDstAmount.getCurrency () == badCurrency ()) ||
|
||||||
|
saDstAmount <= zero)
|
||||||
{
|
{
|
||||||
jvStatus = rpcError (rpcDST_AMT_MALFORMED);
|
jvStatus = rpcError (rpcDST_AMT_MALFORMED);
|
||||||
return PFR_PJ_INVALID;
|
return PFR_PJ_INVALID;
|
||||||
@@ -363,16 +374,16 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
|||||||
if (sourceCurrencies.empty ())
|
if (sourceCurrencies.empty ())
|
||||||
{
|
{
|
||||||
auto usCurrencies =
|
auto usCurrencies =
|
||||||
usAccountSourceCurrencies (raSrcAccount, cache, true);
|
accountSourceCurrencies (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 (std::make_pair (c, xrpAccount()));
|
sourceCurrencies.insert ({c, xrpAccount()});
|
||||||
else
|
else
|
||||||
sourceCurrencies.insert (std::make_pair (c, raSrcAccount.getAccountID ()));
|
sourceCurrencies.insert ({c, raSrcAccount.getAccountID ()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -390,26 +401,30 @@ 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))
|
||||||
@@ -423,7 +438,7 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
|||||||
for (auto const& currIssuer: sourceCurrencies)
|
for (auto const& currIssuer: sourceCurrencies)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
STAmount test ({currIssuer.first, currIssuer.second}, 1);
|
STAmount test (currIssuer, 1);
|
||||||
if (m_journal.debug)
|
if (m_journal.debug)
|
||||||
{
|
{
|
||||||
m_journal.debug
|
m_journal.debug
|
||||||
@@ -431,26 +446,34 @@ 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];
|
||||||
Pathfinder pf (cache, raSrcAccount, raDstAccount,
|
STPath fullLiquidityPath;
|
||||||
currIssuer.first, currIssuer.second, saDstAmount, valid);
|
auto valid = findPathsForOneIssuer (
|
||||||
|
cache,
|
||||||
|
raSrcAccount.getAccountID(),
|
||||||
|
raDstAccount.getAccountID(),
|
||||||
|
currIssuer,
|
||||||
|
saDstAmount,
|
||||||
|
iLevel,
|
||||||
|
4, // iMaxPaths
|
||||||
|
spsPaths,
|
||||||
|
fullLiquidityPath);
|
||||||
CondLog (!valid, lsDEBUG, PathRequest)
|
CondLog (!valid, lsDEBUG, PathRequest)
|
||||||
<< iIdentifier << " PF request not valid";
|
<< iIdentifier << " PF request not valid";
|
||||||
|
|
||||||
STPath extraPath;
|
if (valid)
|
||||||
if (valid && pf.findPaths (iLevel, 4, spsPaths, extraPath))
|
|
||||||
{
|
{
|
||||||
LedgerEntrySet lesSandbox (cache->getLedger (), tapNONE);
|
LedgerEntrySet lesSandbox (cache->getLedger (), tapNONE);
|
||||||
auto& account = currIssuer.second.isNonZero ()
|
auto& account = !isXRP (currIssuer.account)
|
||||||
? Account(currIssuer.second)
|
? currIssuer.account
|
||||||
: isXRP (currIssuer.first)
|
: isXRP (currIssuer.currency)
|
||||||
? xrpAccount()
|
? xrpAccount()
|
||||||
: raSrcAccount.getAccountID ();
|
: raSrcAccount.getAccountID ();
|
||||||
STAmount saMaxAmount ({currIssuer.first, account}, 1);
|
STAmount saMaxAmount ({currIssuer.currency, account}, 1);
|
||||||
|
|
||||||
saMaxAmount.negate ();
|
saMaxAmount.negate ();
|
||||||
m_journal.debug << iIdentifier << " Paths found, calling rippleCalc";
|
m_journal.debug << iIdentifier
|
||||||
|
<< " Paths found, calling rippleCalc";
|
||||||
auto rc = path::RippleCalc::rippleCalculate (
|
auto rc = path::RippleCalc::rippleCalculate (
|
||||||
lesSandbox,
|
lesSandbox,
|
||||||
saMaxAmount,
|
saMaxAmount,
|
||||||
@@ -459,12 +482,12 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
|||||||
raSrcAccount.getAccountID (),
|
raSrcAccount.getAccountID (),
|
||||||
spsPaths);
|
spsPaths);
|
||||||
|
|
||||||
if (!extraPath.empty() &&
|
if (!fullLiquidityPath.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 (extraPath);
|
spsPaths.push_back (fullLiquidityPath);
|
||||||
rc = path::RippleCalc::rippleCalculate (lesSandbox,
|
rc = path::RippleCalc::rippleCalculate (lesSandbox,
|
||||||
saMaxAmount,
|
saMaxAmount,
|
||||||
saDstAmount,
|
saDstAmount,
|
||||||
@@ -484,8 +507,8 @@ 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);
|
||||||
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;
|
||||||
jvArray.append (jvEntry);
|
jvArray.append (jvEntry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 (std::shared_ptr <InfoSub> const& subscriber,
|
PathRequest (
|
||||||
int id, PathRequests&, beast::Journal journal);
|
std::shared_ptr <InfoSub> const& subscriber,
|
||||||
|
int id,
|
||||||
|
PathRequests&,
|
||||||
|
beast::Journal journal);
|
||||||
|
|
||||||
~PathRequest ();
|
~PathRequest ();
|
||||||
|
|
||||||
@@ -97,8 +97,8 @@ private:
|
|||||||
RippleAddress raDstAccount;
|
RippleAddress raDstAccount;
|
||||||
STAmount saDstAmount;
|
STAmount saDstAmount;
|
||||||
|
|
||||||
std::set<CurrencyIssuer> sciSourceCurrencies;
|
std::set<Issue> sciSourceCurrencies;
|
||||||
std::map<CurrencyIssuer, STPathSet> mContext;
|
std::map<Issue, STPathSet> mContext;
|
||||||
|
|
||||||
bool bValid;
|
bool bValid;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
|
#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
|
||||||
@@ -314,13 +316,13 @@ TER PathState::pushNode (
|
|||||||
|
|
||||||
if (resultCode == tesSUCCESS)
|
if (resultCode == tesSUCCESS)
|
||||||
{
|
{
|
||||||
STAmount saOwed = credit_balance (lesEntries,
|
STAmount saOwed = creditBalance (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 = credit_limit (lesEntries,
|
saLimit = creditLimit (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
@@ -33,112 +33,126 @@ class Pathfinder
|
|||||||
public:
|
public:
|
||||||
Pathfinder (
|
Pathfinder (
|
||||||
RippleLineCache::ref cache,
|
RippleLineCache::ref cache,
|
||||||
RippleAddress const& srcAccountID,
|
Account const& srcAccount,
|
||||||
RippleAddress const& dstAccountID,
|
Account const& dstAccount,
|
||||||
Currency const& srcCurrencyID,
|
Currency const& uSrcCurrency,
|
||||||
Account const& srcIssuerID,
|
Account const& uSrcIssuer,
|
||||||
STAmount const& dstAmount,
|
STAmount const& dstAmount);
|
||||||
bool& bValid);
|
|
||||||
|
|
||||||
static void initPathTable();
|
static void initPathTable ();
|
||||||
|
|
||||||
bool findPaths (
|
bool findPaths (int searchLevel);
|
||||||
int iLevel,
|
|
||||||
unsigned int const iMaxPaths,
|
|
||||||
STPathSet& spsDst,
|
|
||||||
STPath& spExtraPath);
|
|
||||||
|
|
||||||
private:
|
void ensurePathsAreComplete (STPathSet&);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
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,
|
pt_nonXRP_to_same, // Destination currency is the same as source.
|
||||||
pt_nonXRP_to_nonXRP
|
pt_nonXRP_to_nonXRP // Destination currency is NOT the same as source.
|
||||||
};
|
};
|
||||||
|
|
||||||
enum NodeType
|
private:
|
||||||
{
|
/*
|
||||||
nt_SOURCE, // The source account with an issuer account, if required
|
Call graph of methoids
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector<NodeType> PathType_t;
|
findPaths:
|
||||||
typedef std::pair<int, PathType_t> CostedPath_t;
|
addPathsForType:
|
||||||
typedef std::vector<CostedPath_t> CostedPathList_t;
|
addLinks:
|
||||||
|
addLink:
|
||||||
|
getPathsOut
|
||||||
|
issueMatchesOrigin
|
||||||
|
isNoRippleOut:
|
||||||
|
isNoRipple
|
||||||
|
|
||||||
typedef std::pair<int, const char*> PathCost;
|
ensurePathsAreComplete
|
||||||
typedef std::vector<PathCost> PathCostList;
|
|
||||||
|
|
||||||
typedef std::map<PaymentType, CostedPathList_t> PathTable;
|
getBestPaths:
|
||||||
|
rippleCalculate
|
||||||
|
getPathLiquidity:
|
||||||
|
rippleCalculate
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/** Fill a CostedPathList_t from its description. */
|
// Add all paths of one type to mCompletePaths.
|
||||||
static void fillPaths(PaymentType type,
|
STPathSet& addPathsForType (PathType const& type);
|
||||||
PathCostList const& costs);
|
|
||||||
|
|
||||||
/** @return true if any building paths are now complete. */
|
bool issueMatchesOrigin (Issue const&);
|
||||||
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& accountID,
|
Account const& account,
|
||||||
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);
|
||||||
|
|
||||||
void addLink(
|
// Call addLink() for each path in currentPaths.
|
||||||
|
void addLinks (
|
||||||
STPathSet const& currentPaths,
|
STPathSet const& currentPaths,
|
||||||
STPathSet& incompletePaths,
|
STPathSet& incompletePaths,
|
||||||
int addFlags);
|
int addFlags);
|
||||||
|
|
||||||
STPathSet& getPaths(PathType_t const& type,
|
// Compute the liquidity for a path. Return tesSUCCESS if it has has enough
|
||||||
bool addComplete = true);
|
// liquidity to be worth keeping, otherwise an error.
|
||||||
|
TER getPathLiquidity (
|
||||||
STPathSet filterPaths(int iMaxPaths,
|
STPath const& path, // IN: The path to check.
|
||||||
STPath& extraPath);
|
STAmount const& minDstAmount, // IN: The minimum output this path must
|
||||||
|
// deliver to be worth keeping.
|
||||||
TER checkPath (STPath const& path, STAmount const& minDestAmount,
|
STAmount& amountOut, // OUT: The actual liquidity on the path.
|
||||||
STAmount& amount, uint64_t& quality) const;
|
uint64_t& qualityOut) const; // OUT: The returned initial quality
|
||||||
|
|
||||||
|
// 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& setByID,
|
Account const& fromAccount,
|
||||||
Account const& setOnID,
|
Account const& toAccount,
|
||||||
Currency const& currencyID);
|
Currency const& currency);
|
||||||
|
|
||||||
// Our main table of paths
|
Account mSrcAccount;
|
||||||
|
Account mDstAccount;
|
||||||
|
STAmount mDstAmount;
|
||||||
|
Currency mSrcCurrency;
|
||||||
|
Account mSrcIssuer;
|
||||||
|
STAmount mSrcAmount;
|
||||||
|
|
||||||
static PathTable mPathTable;
|
Ledger::pointer mLedger;
|
||||||
static PathType_t makePath(char const*);
|
LoadEvent::pointer m_loadEvent;
|
||||||
|
RippleLineCache::pointer mRLCache;
|
||||||
Account mSrcAccountID;
|
|
||||||
Account mDstAccountID;
|
|
||||||
STAmount mDstAmount;
|
|
||||||
Currency mSrcCurrencyID;
|
|
||||||
Account mSrcIssuerID;
|
|
||||||
STAmount mSrcAmount;
|
|
||||||
|
|
||||||
Ledger::pointer mLedger;
|
|
||||||
LoadEvent::pointer m_loadEvent;
|
|
||||||
RippleLineCache::pointer mRLCache;
|
|
||||||
|
|
||||||
STPathElement mSource;
|
STPathElement mSource;
|
||||||
STPathSet mCompletePaths;
|
STPathSet mCompletePaths;
|
||||||
std::map<PathType_t, STPathSet> mPaths;
|
std::map<PathType, STPathSet> mPaths;
|
||||||
|
|
||||||
hash_map<Issue, int> mPathsOutCountMap;
|
hash_map<Issue, int> mPathsOutCountMap;
|
||||||
|
|
||||||
@@ -146,51 +160,18 @@ private:
|
|||||||
static std::uint32_t const afADD_ACCOUNTS = 0x001;
|
static std::uint32_t const afADD_ACCOUNTS = 0x001;
|
||||||
|
|
||||||
// Add order books
|
// Add order books
|
||||||
static std::uint32_t const afADD_BOOKS = 0x002;
|
static std::uint32_t const afADD_BOOKS = 0x002;
|
||||||
|
|
||||||
// Add order book to XRP only
|
// Add order book to XRP only
|
||||||
static std::uint32_t const afOB_XRP = 0x010;
|
static std::uint32_t const afOB_XRP = 0x010;
|
||||||
|
|
||||||
// Must link to destination currency
|
// Must link to destination currency
|
||||||
static std::uint32_t const afOB_LAST = 0x040;
|
static std::uint32_t const afOB_LAST = 0x040;
|
||||||
|
|
||||||
// Destination account only
|
// Destination account only
|
||||||
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
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#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 {
|
||||||
@@ -46,8 +47,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();
|
||||||
@@ -80,7 +81,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)
|
||||||
? credit_balance (ledger(),
|
? creditBalance (ledger(),
|
||||||
node().account_,
|
node().account_,
|
||||||
previousAccountID,
|
previousAccountID,
|
||||||
node().issue_.currency)
|
node().issue_.currency)
|
||||||
@@ -88,7 +89,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)
|
||||||
? credit_limit (ledger(),
|
? creditLimit (ledger(),
|
||||||
node().account_,
|
node().account_,
|
||||||
previousAccountID,
|
previousAccountID,
|
||||||
node().issue_.currency)
|
node().issue_.currency)
|
||||||
@@ -96,7 +97,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)
|
||||||
? credit_balance (ledger(),
|
? creditBalance (ledger(),
|
||||||
node().account_,
|
node().account_,
|
||||||
nextAccountID,
|
nextAccountID,
|
||||||
node().issue_.currency)
|
node().issue_.currency)
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
|
#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 {
|
||||||
@@ -119,11 +121,10 @@ Json::Value doRipplePathFind (RPC::Context& context)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto usCurrencies = usAccountSourceCurrencies (raSrc, cache, true);
|
auto currencies = accountSourceCurrencies (raSrc, cache, true);
|
||||||
|
|
||||||
jvSrcCurrencies = Json::Value (Json::arrayValue);
|
jvSrcCurrencies = Json::Value (Json::arrayValue);
|
||||||
|
|
||||||
for (auto const& uCurrency: usCurrencies)
|
for (auto const& uCurrency: currencies)
|
||||||
{
|
{
|
||||||
Json::Value jvCurrency (Json::objectValue);
|
Json::Value jvCurrency (Json::objectValue);
|
||||||
jvCurrency["currency"] = to_string(uCurrency);
|
jvCurrency["currency"] = to_string(uCurrency);
|
||||||
@@ -134,7 +135,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);
|
||||||
|
|
||||||
auto usDestCurrID = usAccountDestCurrencies (raDst, cache, true);
|
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));
|
||||||
|
|
||||||
@@ -177,11 +178,6 @@ 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())
|
||||||
@@ -196,6 +192,7 @@ 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"]);
|
||||||
@@ -205,8 +202,18 @@ Json::Value doRipplePathFind (RPC::Context& context)
|
|||||||
spsComputed = paths.object.get()->downcast<STPathSet> ();
|
spsComputed = paths.object.get()->downcast<STPathSet> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
STPath extraPath;
|
STPath fullLiquidityPath;
|
||||||
if (!bValid || !pf.findPaths (level, 4, spsComputed, extraPath))
|
auto valid = findPathsForOneIssuer(
|
||||||
|
cache,
|
||||||
|
raSrc.getAccountID(),
|
||||||
|
raDst.getAccountID(),
|
||||||
|
{uSrcCurrencyID, uSrcIssuerID},
|
||||||
|
saDstAmount,
|
||||||
|
level,
|
||||||
|
4, // iMaxPaths
|
||||||
|
spsComputed,
|
||||||
|
fullLiquidityPath);
|
||||||
|
if (!valid)
|
||||||
{
|
{
|
||||||
WriteLog (lsWARNING, RPCHandler)
|
WriteLog (lsWARNING, RPCHandler)
|
||||||
<< "ripple_path_find: No paths found.";
|
<< "ripple_path_find: No paths found.";
|
||||||
@@ -241,13 +248,13 @@ Json::Value doRipplePathFind (RPC::Context& context)
|
|||||||
<< " saMaxAmountAct=" << rc.actualAmountIn
|
<< " saMaxAmountAct=" << rc.actualAmountIn
|
||||||
<< " saDstAmountAct=" << rc.actualAmountOut;
|
<< " saDstAmountAct=" << rc.actualAmountOut;
|
||||||
|
|
||||||
if (extraPath.size() > 0 &&
|
if (fullLiquidityPath.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 (extraPath);
|
spsComputed.push_back (fullLiquidityPath);
|
||||||
lesSandbox.clear ();
|
lesSandbox.clear ();
|
||||||
rc = path::RippleCalc::rippleCalculate (
|
rc = path::RippleCalc::rippleCalculate (
|
||||||
lesSandbox,
|
lesSandbox,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
|
#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>
|
||||||
@@ -152,22 +153,20 @@ 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);
|
||||||
Pathfinder pf (
|
STPath fullLiquidityPath;
|
||||||
|
auto valid = findPathsForOneIssuer (
|
||||||
cache,
|
cache,
|
||||||
raSrcAddressID,
|
raSrcAddressID.getAccountID(),
|
||||||
dstAccountID,
|
dstAccountID.getAccountID(),
|
||||||
saSendMax.getCurrency (),
|
saSendMax.issue (),
|
||||||
saSendMax.getIssuer (),
|
amount,
|
||||||
amount, bValid);
|
getConfig ().PATH_SEARCH_OLD,
|
||||||
|
4, // iMaxPaths
|
||||||
|
spsPaths,
|
||||||
|
fullLiquidityPath);
|
||||||
|
|
||||||
STPath extraPath;
|
if (!valid)
|
||||||
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.";
|
||||||
|
|||||||
@@ -117,7 +117,5 @@
|
|||||||
#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
|
||||||
|
|||||||
@@ -29,5 +29,8 @@
|
|||||||
#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>
|
||||||
|
|||||||
Reference in New Issue
Block a user