mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 02:55:50 +00:00
Compare commits
3 Commits
0.26.4-sp1
...
0.26.4-sp2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95f31b98a8 | ||
|
|
10d74ed100 | ||
|
|
8a7f612d5b |
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -17,31 +17,27 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#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)
|
||||||
, 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";
|
||||||
@@ -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,15 +223,11 @@ 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;
|
||||||
@@ -277,12 +268,10 @@ 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 <= zero)
|
||||||
(saDstAmount.getCurrency () == badCurrency ()) ||
|
|
||||||
saDstAmount <= zero)
|
|
||||||
{
|
{
|
||||||
jvStatus = rpcError (rpcDST_AMT_MALFORMED);
|
jvStatus = rpcError (rpcDST_AMT_MALFORMED);
|
||||||
return PFR_PJ_INVALID;
|
return PFR_PJ_INVALID;
|
||||||
@@ -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,10 +484,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);
|
||||||
rc.actualAmountIn.setIssuer (sourceAccount);
|
jvEntry["source_amount"] = rc.actualAmountIn.getJson (0);
|
||||||
|
jvEntry["paths_computed"] = spsPaths.getJson (0);
|
||||||
jvEntry["source_amount"] = rc.actualAmountIn.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 (
|
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;
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -31,160 +31,114 @@ 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;
|
|
||||||
STAmount mDstAmount;
|
|
||||||
Currency mSrcCurrency;
|
|
||||||
boost::optional<Account> mSrcIssuer;
|
|
||||||
STAmount mSrcAmount;
|
|
||||||
/** The amount remaining from mSrcAccount after the default liquidity has
|
|
||||||
been removed. */
|
|
||||||
STAmount mRemainingAmount;
|
|
||||||
|
|
||||||
Ledger::pointer mLedger;
|
static PathTable mPathTable;
|
||||||
LoadEvent::pointer m_loadEvent;
|
static PathType_t makePath(char const*);
|
||||||
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::vector<PathRank> mPathRanks;
|
std::map<PathType_t, STPathSet> mPaths;
|
||||||
std::map<PathType, STPathSet> mPaths;
|
|
||||||
|
|
||||||
hash_map<Issue, int> mPathsOutCountMap;
|
hash_map<Issue, int> mPathsOutCountMap;
|
||||||
|
|
||||||
@@ -192,18 +146,51 @@ 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,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)
|
||||||
|
|||||||
@@ -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:
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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.";
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user