mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Path find cleanup (RIPD-1023)
This commit is contained in:
committed by
Vinnie Falco
parent
3af0c38315
commit
20f186d855
@@ -39,7 +39,7 @@
|
||||
#include <ripple/app/misc/NetworkOPs.h>
|
||||
#include <ripple/app/misc/SHAMapStore.h>
|
||||
#include <ripple/app/misc/Validations.h>
|
||||
#include <ripple/app/paths/FindPaths.h>
|
||||
#include <ripple/app/paths/Pathfinder.h>
|
||||
#include <ripple/app/paths/PathRequests.h>
|
||||
#include <ripple/app/misc/UniqueNodeList.h>
|
||||
#include <ripple/app/tx/InboundTransactions.h>
|
||||
@@ -931,7 +931,7 @@ void ApplicationImp::setup()
|
||||
|
||||
m_amendmentTable->addInitial (
|
||||
config_->section (SECTION_AMENDMENTS));
|
||||
initializePathfinding ();
|
||||
Pathfinder::initPathTable();
|
||||
|
||||
m_ledgerMaster->setMinValidations (
|
||||
config_->VALIDATION_QUORUM, config_->LOCK_QUORUM);
|
||||
|
||||
@@ -312,8 +312,7 @@ int PathRequest::parseJson (Json::Value const& jvParams)
|
||||
return PFR_PJ_INVALID;
|
||||
}
|
||||
|
||||
convert_all_ =
|
||||
saDstAmount == STAmount(saDstAmount.issue(), 1u, 0, true);
|
||||
convert_all_ = saDstAmount == STAmount(saDstAmount.issue(), 1u, 0, true);
|
||||
|
||||
if ((saDstAmount.getCurrency ().isZero () &&
|
||||
saDstAmount.getIssuer ().isNonZero ()) ||
|
||||
@@ -447,97 +446,155 @@ void PathRequest::resetLevel (int l)
|
||||
iLastLevel = l;
|
||||
}
|
||||
|
||||
bool
|
||||
PathRequest::findPaths (
|
||||
RippleLineCache::ref cache,
|
||||
FindPaths& fp, Issue const& issue,
|
||||
Json::Value& jvArray)
|
||||
std::unique_ptr<Pathfinder> const&
|
||||
PathRequest::getPathFinder(RippleLineCache::ref cache,
|
||||
hash_map<Currency, std::unique_ptr<Pathfinder>>& currency_map,
|
||||
Currency const& currency, STAmount const& dst_amount,
|
||||
int const level)
|
||||
{
|
||||
STPath fullLiquidityPath;
|
||||
auto result = fp.findPathsForIssue(issue,
|
||||
mContext[issue], fullLiquidityPath, app_);
|
||||
if (! result)
|
||||
auto i = currency_map.find(currency);
|
||||
if (i != currency_map.end())
|
||||
return i->second;
|
||||
auto pathfinder = std::make_unique<Pathfinder>(
|
||||
cache, *raSrcAccount, *raDstAccount, currency,
|
||||
boost::none, dst_amount, saSendMax, app_);
|
||||
if (pathfinder->findPaths(level))
|
||||
pathfinder->computePathRanks(max_paths_);
|
||||
else
|
||||
pathfinder.reset(); // It's a bad request - clear it.
|
||||
return currency_map[currency] = std::move(pathfinder);
|
||||
}
|
||||
|
||||
void
|
||||
PathRequest::findPaths (RippleLineCache::ref cache, int const level,
|
||||
Json::Value& jvArray)
|
||||
{
|
||||
auto sourceCurrencies = sciSourceCurrencies;
|
||||
if (sourceCurrencies.empty ())
|
||||
{
|
||||
m_journal.debug << iIdentifier << " No paths found";
|
||||
return false;
|
||||
}
|
||||
mContext[issue] = *result;
|
||||
|
||||
boost::optional<PaymentSandbox> sandbox;
|
||||
sandbox.emplace(&*cache->getLedger(), tapNONE);
|
||||
|
||||
auto& sourceAccount = ! isXRP(issue.account)
|
||||
? issue.account
|
||||
: isXRP(issue.currency)
|
||||
? xrpAccount()
|
||||
: *raSrcAccount;
|
||||
|
||||
STAmount saMaxAmount = saSendMax.value_or(
|
||||
STAmount({issue.currency, sourceAccount}, 1u, 0, true));
|
||||
|
||||
m_journal.debug << iIdentifier
|
||||
<< " Paths found, calling rippleCalc";
|
||||
|
||||
path::RippleCalc::Input rcInput;
|
||||
if (convert_all_)
|
||||
rcInput.partialPaymentAllowed = true;
|
||||
|
||||
auto rc = path::RippleCalc::rippleCalculate(
|
||||
*sandbox, saMaxAmount,
|
||||
convert_all_ ? STAmount(saDstAmount.issue(), STAmount::cMaxValue,
|
||||
STAmount::cMaxOffset) : saDstAmount,
|
||||
*raDstAccount, *raSrcAccount, *result,
|
||||
app_.logs (), &rcInput);
|
||||
|
||||
if (! convert_all_ &&
|
||||
! fullLiquidityPath.empty() &&
|
||||
(rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL))
|
||||
{
|
||||
m_journal.debug << iIdentifier
|
||||
<< " Trying with an extra path element";
|
||||
result->push_back(fullLiquidityPath);
|
||||
sandbox.emplace(&*cache->getLedger(), tapNONE);
|
||||
|
||||
rc = path::RippleCalc::rippleCalculate(
|
||||
*sandbox, saMaxAmount, saDstAmount,
|
||||
*raDstAccount, *raSrcAccount, *result, app_.logs ());
|
||||
if (rc.result() != tesSUCCESS)
|
||||
auto usCurrencies =
|
||||
accountSourceCurrencies(*raSrcAccount, cache, true);
|
||||
bool sameAccount = *raSrcAccount == *raDstAccount;
|
||||
for (auto const& c : usCurrencies)
|
||||
{
|
||||
m_journal.warning << iIdentifier
|
||||
<< " Failed with covering path "
|
||||
<< transHuman(rc.result());
|
||||
if (!sameAccount || (c != saDstAmount.getCurrency()))
|
||||
{
|
||||
sourceCurrencies.insert(
|
||||
{c, c.isZero() ? xrpAccount() : *raSrcAccount});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto const dst_amount = convert_all_ ?
|
||||
STAmount(saDstAmount.issue(), STAmount::cMaxValue, STAmount::cMaxOffset)
|
||||
: saDstAmount;
|
||||
hash_map<Currency, std::unique_ptr<Pathfinder>> currency_map;
|
||||
for (auto const& issue : sourceCurrencies)
|
||||
{
|
||||
JLOG(m_journal.debug)
|
||||
<< iIdentifier
|
||||
<< " Trying to find paths: "
|
||||
<< STAmount(issue, 1).getFullText();
|
||||
|
||||
auto& pathfinder = getPathFinder(cache, currency_map,
|
||||
issue.currency, dst_amount, level);
|
||||
if (! pathfinder)
|
||||
{
|
||||
assert(false);
|
||||
m_journal.debug << iIdentifier << " No paths found";
|
||||
continue;
|
||||
}
|
||||
|
||||
STPath fullLiquidityPath;
|
||||
auto ps = pathfinder->getBestPaths(max_paths_,
|
||||
fullLiquidityPath, mContext[issue], issue.account);
|
||||
mContext[issue] = ps;
|
||||
|
||||
auto& sourceAccount = ! isXRP(issue.account)
|
||||
? issue.account
|
||||
: isXRP(issue.currency)
|
||||
? xrpAccount()
|
||||
: *raSrcAccount;
|
||||
STAmount saMaxAmount = saSendMax.value_or(
|
||||
STAmount({issue.currency, sourceAccount}, 1u, 0, true));
|
||||
|
||||
m_journal.debug << iIdentifier
|
||||
<< " Paths found, calling rippleCalc";
|
||||
|
||||
path::RippleCalc::Input rcInput;
|
||||
if (convert_all_)
|
||||
rcInput.partialPaymentAllowed = true;
|
||||
auto sandbox = std::make_unique<PaymentSandbox>
|
||||
(&*cache->getLedger(), tapNONE);
|
||||
auto rc = path::RippleCalc::rippleCalculate(
|
||||
*sandbox,
|
||||
saMaxAmount, // --> Amount to send is unlimited
|
||||
// to get an estimate.
|
||||
dst_amount, // --> Amount to deliver.
|
||||
*raDstAccount, // --> Account to deliver to.
|
||||
*raSrcAccount, // --> Account sending from.
|
||||
ps, // --> Path set.
|
||||
app_.logs(),
|
||||
&rcInput);
|
||||
|
||||
if (! convert_all_ &&
|
||||
! fullLiquidityPath.empty() &&
|
||||
(rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL))
|
||||
{
|
||||
m_journal.debug << iIdentifier
|
||||
<< " Trying with an extra path element";
|
||||
|
||||
ps.push_back(fullLiquidityPath);
|
||||
sandbox = std::make_unique<PaymentSandbox>
|
||||
(&*cache->getLedger(), tapNONE);
|
||||
rc = path::RippleCalc::rippleCalculate(
|
||||
*sandbox,
|
||||
saMaxAmount, // --> Amount to send is unlimited
|
||||
// to get an estimate.
|
||||
dst_amount, // --> Amount to deliver.
|
||||
*raDstAccount, // --> Account to deliver to.
|
||||
*raSrcAccount, // --> Account sending from.
|
||||
ps, // --> Path set.
|
||||
app_.logs());
|
||||
|
||||
if (rc.result() != tesSUCCESS)
|
||||
{
|
||||
m_journal.warning << iIdentifier
|
||||
<< " Failed with covering path "
|
||||
<< transHuman(rc.result());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.debug << iIdentifier
|
||||
<< " Extra path element gives "
|
||||
<< transHuman(rc.result());
|
||||
}
|
||||
}
|
||||
|
||||
if (rc.result () == tesSUCCESS)
|
||||
{
|
||||
Json::Value jvEntry (Json::objectValue);
|
||||
rc.actualAmountIn.setIssuer (sourceAccount);
|
||||
jvEntry[jss::source_amount] = rc.actualAmountIn.getJson (0);
|
||||
jvEntry[jss::paths_computed] = ps.getJson(0);
|
||||
|
||||
if (convert_all_)
|
||||
jvEntry[jss::destination_amount] = rc.actualAmountOut.getJson(0);
|
||||
|
||||
if (hasCompletion ())
|
||||
{
|
||||
// Old ripple_path_find API requires this
|
||||
jvEntry[jss::paths_canonical] = Json::arrayValue;
|
||||
}
|
||||
|
||||
jvArray.append (jvEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.debug << iIdentifier
|
||||
<< " Extra path element gives "
|
||||
m_journal.debug << iIdentifier << " rippleCalc returns "
|
||||
<< transHuman(rc.result());
|
||||
}
|
||||
}
|
||||
|
||||
if (rc.result () == tesSUCCESS)
|
||||
{
|
||||
Json::Value jvEntry (Json::objectValue);
|
||||
rc.actualAmountIn.setIssuer (sourceAccount);
|
||||
jvEntry[jss::source_amount] = rc.actualAmountIn.getJson (0);
|
||||
jvEntry[jss::paths_computed] = result->getJson(0);
|
||||
|
||||
if (convert_all_)
|
||||
jvEntry[jss::destination_amount] = rc.actualAmountOut.getJson(0);
|
||||
|
||||
if (hasCompletion ())
|
||||
{
|
||||
// Old ripple_path_find API requires this
|
||||
jvEntry[jss::paths_canonical] = Json::arrayValue;
|
||||
}
|
||||
|
||||
jvArray.append (jvEntry);
|
||||
return true;
|
||||
}
|
||||
|
||||
m_journal.debug << iIdentifier << " rippleCalc returns "
|
||||
<< transHuman (rc.result ());
|
||||
return false;
|
||||
}
|
||||
|
||||
Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
||||
@@ -550,25 +607,6 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
||||
return jvStatus;
|
||||
jvStatus = Json::objectValue;
|
||||
|
||||
auto sourceCurrencies = sciSourceCurrencies;
|
||||
|
||||
if (sourceCurrencies.empty ())
|
||||
{
|
||||
auto usCurrencies =
|
||||
accountSourceCurrencies (*raSrcAccount, cache, true);
|
||||
bool sameAccount = *raSrcAccount == *raDstAccount;
|
||||
for (auto const& c: usCurrencies)
|
||||
{
|
||||
if (!sameAccount || (c != saDstAmount.getCurrency ()))
|
||||
{
|
||||
if (c.isZero ())
|
||||
sourceCurrencies.insert ({c, xrpAccount()});
|
||||
else
|
||||
sourceCurrencies.insert ({c, *raSrcAccount});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasCompletion ())
|
||||
{
|
||||
// Old ripple_path_find API gives destination_currencies
|
||||
@@ -622,29 +660,10 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
||||
|
||||
m_journal.debug << iIdentifier << " processing at level " << iLevel;
|
||||
|
||||
bool found = false;
|
||||
Json::Value jvArray = Json::arrayValue;
|
||||
FindPaths fp (
|
||||
cache,
|
||||
*raSrcAccount,
|
||||
*raDstAccount,
|
||||
convert_all_ ? STAmount(saDstAmount.issue(), STAmount::cMaxValue,
|
||||
STAmount::cMaxOffset) : saDstAmount,
|
||||
saSendMax,
|
||||
iLevel,
|
||||
4); // iMaxPaths
|
||||
for (auto const& i: sourceCurrencies)
|
||||
{
|
||||
JLOG(m_journal.debug)
|
||||
<< iIdentifier
|
||||
<< " Trying to find paths: "
|
||||
<< STAmount(i, 1).getFullText();
|
||||
if (findPaths(cache, fp, i, jvArray))
|
||||
found = true;
|
||||
}
|
||||
|
||||
findPaths(cache, iLevel, jvArray);
|
||||
bLastSuccess = jvArray.size();
|
||||
iLastLevel = iLevel;
|
||||
bLastSuccess = found;
|
||||
|
||||
if (fast && ptQuickReply.is_not_a_date_time())
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#define RIPPLE_APP_PATHS_PATHREQUEST_H_INCLUDED
|
||||
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/app/paths/FindPaths.h>
|
||||
#include <ripple/app/paths/Pathfinder.h>
|
||||
#include <ripple/app/paths/RippleLineCache.h>
|
||||
#include <ripple/json/json_value.h>
|
||||
#include <ripple/net/InfoSub.h>
|
||||
@@ -98,10 +98,13 @@ private:
|
||||
void setValid ();
|
||||
void resetLevel (int level);
|
||||
|
||||
bool
|
||||
findPaths (RippleLineCache::ref,
|
||||
FindPaths&, Issue const&,
|
||||
Json::Value& jvArray);
|
||||
std::unique_ptr<Pathfinder> const&
|
||||
getPathFinder(RippleLineCache::ref,
|
||||
hash_map<Currency, std::unique_ptr<Pathfinder>>&, Currency const&,
|
||||
STAmount const&, int const);
|
||||
|
||||
void
|
||||
findPaths (RippleLineCache::ref, int const, Json::Value&);
|
||||
|
||||
int parseJson (Json::Value const&);
|
||||
|
||||
@@ -141,6 +144,8 @@ private:
|
||||
boost::posix_time::ptime ptCreated;
|
||||
boost::posix_time::ptime ptQuickReply;
|
||||
boost::posix_time::ptime ptFullReply;
|
||||
|
||||
static unsigned int const max_paths_ = 4;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/json/json_reader.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/protocol/JsonFields.h>
|
||||
@@ -151,16 +150,17 @@ find_paths(jtx::Env& env,
|
||||
jvCurrency[jss::currency] = to_string(c);
|
||||
jvSrcCurrencies.append(jvCurrency);
|
||||
}
|
||||
|
||||
auto const convert_all =
|
||||
saDstAmount == STAmount(saDstAmount.issue(), 1u, 0, true);
|
||||
auto result = ripplePathFind(cache, src.id(), dst.id(),
|
||||
saDstAmount, jvSrcCurrencies, boost::none, level, saSendMax,
|
||||
saDstAmount == STAmount(saDstAmount.issue(), 1u, 0, true), env.app ());
|
||||
(convert_all ? STAmount(saDstAmount.issue(), STAmount::cMaxValue,
|
||||
STAmount::cMaxOffset) : saDstAmount), jvSrcCurrencies, boost::none,
|
||||
level, saSendMax, convert_all, env.app());
|
||||
if (! result.first)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Path_test::findPath: ripplePathFind find failed");
|
||||
}
|
||||
|
||||
auto const& jv = result.second[0u];
|
||||
Json::Value paths;
|
||||
paths["Paths"] = jv["paths_computed"];
|
||||
|
||||
@@ -31,7 +31,7 @@ ripplePathFind (RippleLineCache::pointer const& cache,
|
||||
STAmount const& saDstAmount,
|
||||
Json::Value const& jvSrcCurrencies,
|
||||
boost::optional<Json::Value> const& contextPaths,
|
||||
int const& level, boost::optional<STAmount> saSendMax,
|
||||
int const level, boost::optional<STAmount> saSendMax,
|
||||
bool convert_all, Application& app);
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/misc/NetworkOPs.h>
|
||||
#include <ripple/app/paths/AccountCurrencies.h>
|
||||
#include <ripple/app/paths/FindPaths.h>
|
||||
#include <ripple/app/paths/PathRequest.h>
|
||||
#include <ripple/app/paths/PathRequests.h>
|
||||
#include <ripple/app/paths/RippleCalc.h>
|
||||
@@ -48,6 +47,8 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
static unsigned int const max_paths = 4;
|
||||
|
||||
static
|
||||
Json::Value
|
||||
buildSrcCurrencies(AccountID const& account,
|
||||
@@ -246,9 +247,11 @@ Json::Value doRipplePathFind (RPC::Context& context)
|
||||
auto contextPaths = context.params.isMember(jss::paths) ?
|
||||
boost::optional<Json::Value>(context.params[jss::paths]) :
|
||||
boost::optional<Json::Value>(boost::none);
|
||||
auto pathFindResult = ripplePathFind(cache, raSrc, raDst, saDstAmount,
|
||||
jvSrcCurrencies, contextPaths, level, saSendMax, convert_all,
|
||||
context.app);
|
||||
auto pathFindResult = ripplePathFind(
|
||||
cache, raSrc, raDst, (convert_all ? STAmount(saDstAmount.issue(),
|
||||
STAmount::cMaxValue, STAmount::cMaxOffset) : saDstAmount),
|
||||
jvSrcCurrencies, contextPaths, level, saSendMax,
|
||||
convert_all, context.app);
|
||||
if (!pathFindResult.first)
|
||||
return pathFindResult.second;
|
||||
|
||||
@@ -262,26 +265,35 @@ Json::Value doRipplePathFind (RPC::Context& context)
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
std::unique_ptr<Pathfinder> const&
|
||||
getPathFinder(RippleLineCache::ref cache, AccountID const& raSrc,
|
||||
AccountID const& raDst, boost::optional<STAmount> saSendMax,
|
||||
hash_map<Currency, std::unique_ptr<Pathfinder>>& currency_map,
|
||||
Currency const& currency, STAmount const& dst_amount,
|
||||
int const level, Application& app)
|
||||
{
|
||||
auto i = currency_map.find(currency);
|
||||
if (i != currency_map.end())
|
||||
return i->second;
|
||||
auto pathfinder = std::make_unique<Pathfinder>(cache, raSrc, raDst,
|
||||
currency, boost::none, dst_amount, saSendMax, app);
|
||||
if (pathfinder->findPaths(level))
|
||||
pathfinder->computePathRanks(max_paths);
|
||||
else
|
||||
pathfinder.reset(); // It's a bad request - clear it.
|
||||
return currency_map[currency] = std::move(pathfinder);
|
||||
}
|
||||
|
||||
std::pair<bool, Json::Value>
|
||||
ripplePathFind (RippleLineCache::pointer const& cache,
|
||||
AccountID const& raSrc, AccountID const& raDst,
|
||||
STAmount const& saDstAmount, Json::Value const& jvSrcCurrencies,
|
||||
boost::optional<Json::Value> const& contextPaths,
|
||||
int const& level, boost::optional<STAmount> saSendMax,
|
||||
int const level, boost::optional<STAmount> saSendMax,
|
||||
bool convert_all, Application& app)
|
||||
{
|
||||
auto const sa = STAmount(saDstAmount.issue(),
|
||||
STAmount::cMaxValue, STAmount::cMaxOffset);
|
||||
FindPaths fp(
|
||||
cache,
|
||||
raSrc,
|
||||
raDst,
|
||||
convert_all ? sa : saDstAmount,
|
||||
saSendMax,
|
||||
level,
|
||||
4); // max paths
|
||||
|
||||
Json::Value jvArray(Json::arrayValue);
|
||||
hash_map<Currency, std::unique_ptr<Pathfinder>> currency_map;
|
||||
|
||||
auto j = app.journal ("RPCHandler");
|
||||
|
||||
@@ -350,118 +362,111 @@ ripplePathFind (RippleLineCache::pointer const& cache,
|
||||
STParsedJSONObject paths("pathSet", pathSet);
|
||||
if (! paths.object)
|
||||
return std::make_pair(false, paths.error);
|
||||
else
|
||||
{
|
||||
spsComputed = paths.object->getFieldPathSet(sfPaths);
|
||||
JLOG (j.trace) << "ripple_path_find: Paths: " <<
|
||||
spsComputed.getJson(0);
|
||||
}
|
||||
|
||||
spsComputed = paths.object->getFieldPathSet(sfPaths);
|
||||
JLOG (j.trace) << "ripple_path_find: Paths: " <<
|
||||
spsComputed.getJson(0);
|
||||
}
|
||||
|
||||
auto& pathfinder = getPathFinder(cache, raSrc, raDst, saSendMax,
|
||||
currency_map, issue.currency, saDstAmount, level, app);
|
||||
if (! pathfinder)
|
||||
{
|
||||
JLOG (j.warning) << "ripple_path_find: No paths found.";
|
||||
continue;
|
||||
}
|
||||
|
||||
STPath fullLiquidityPath;
|
||||
auto result = fp.findPathsForIssue(
|
||||
issue,
|
||||
spsComputed,
|
||||
fullLiquidityPath,
|
||||
app);
|
||||
if (! result)
|
||||
auto ps = pathfinder->getBestPaths(max_paths,
|
||||
fullLiquidityPath, spsComputed, issue.account);
|
||||
auto& issuer =
|
||||
isXRP(uSrcIssuerID) ?
|
||||
isXRP(uSrcCurrencyID) ? // Default to source account.
|
||||
xrpAccount() :
|
||||
(raSrc)
|
||||
: uSrcIssuerID; // Use specifed issuer.
|
||||
STAmount saMaxAmount = saSendMax.value_or(
|
||||
STAmount({uSrcCurrencyID, issuer}, 1u, 0, true));
|
||||
|
||||
boost::optional<PaymentSandbox> sandbox;
|
||||
sandbox.emplace(&*cache->getLedger(), tapNONE);
|
||||
assert(sandbox->open());
|
||||
|
||||
path::RippleCalc::Input rcInput;
|
||||
if (convert_all)
|
||||
rcInput.partialPaymentAllowed = true;
|
||||
|
||||
auto rc = path::RippleCalc::rippleCalculate(
|
||||
*sandbox,
|
||||
saMaxAmount, // --> Amount to send is unlimited
|
||||
// to get an estimate.
|
||||
saDstAmount, // --> Amount to deliver.
|
||||
raDst, // --> Account to deliver to.
|
||||
raSrc, // --> Account sending from.
|
||||
ps, // --> Path set.
|
||||
app.logs(),
|
||||
&rcInput);
|
||||
|
||||
JLOG(j.warning)
|
||||
<< "ripple_path_find:"
|
||||
<< " saMaxAmount=" << saMaxAmount
|
||||
<< " saDstAmount=" << saDstAmount
|
||||
<< " saMaxAmountAct=" << rc.actualAmountIn
|
||||
<< " saDstAmountAct=" << rc.actualAmountOut;
|
||||
|
||||
if (! convert_all &&
|
||||
! fullLiquidityPath.empty() &&
|
||||
(rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL))
|
||||
{
|
||||
JLOG (j.warning)
|
||||
<< "ripple_path_find: No paths found.";
|
||||
auto jpr = app.journal("PathRequest");
|
||||
JLOG(jpr.debug)
|
||||
<< "Trying with an extra path element";
|
||||
ps.push_back(fullLiquidityPath);
|
||||
sandbox.emplace(&*cache->getLedger(), tapNONE);
|
||||
assert(sandbox->open());
|
||||
rc = path::RippleCalc::rippleCalculate(
|
||||
*sandbox,
|
||||
saMaxAmount, // --> Amount to send is unlimited
|
||||
// to get an estimate.
|
||||
saDstAmount, // --> Amount to deliver.
|
||||
raDst, // --> Account to deliver to.
|
||||
raSrc, // --> Account sending from.
|
||||
ps, // --> Path set.
|
||||
app.logs());
|
||||
JLOG(jpr.debug)
|
||||
<< "Extra path element gives "
|
||||
<< transHuman(rc.result());
|
||||
}
|
||||
|
||||
if (rc.result() == tesSUCCESS)
|
||||
{
|
||||
Json::Value jvEntry(Json::objectValue);
|
||||
|
||||
STPathSet spsCanonical;
|
||||
|
||||
// Reuse the expanded as it would need to be calcuated
|
||||
// anyway to produce the canonical. (At least unless we
|
||||
// make a direct canonical.)
|
||||
|
||||
jvEntry[jss::source_amount] = rc.actualAmountIn.getJson(0);
|
||||
jvEntry[jss::paths_canonical] = Json::arrayValue;
|
||||
jvEntry[jss::paths_computed] = ps.getJson(0);
|
||||
|
||||
if (convert_all)
|
||||
jvEntry[jss::destination_amount] = rc.actualAmountOut.getJson(0);
|
||||
|
||||
jvArray.append(jvEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& issuer =
|
||||
isXRP(uSrcIssuerID) ?
|
||||
isXRP(uSrcCurrencyID) ? // Default to source account.
|
||||
xrpAccount() :
|
||||
(raSrc)
|
||||
: uSrcIssuerID; // Use specifed issuer.
|
||||
STAmount saMaxAmount = saSendMax.value_or(
|
||||
STAmount({uSrcCurrencyID, issuer}, 1u, 0, true));
|
||||
|
||||
boost::optional<PaymentSandbox> sandbox;
|
||||
sandbox.emplace(&*cache->getLedger(), tapNONE);
|
||||
assert(sandbox->open());
|
||||
|
||||
path::RippleCalc::Input rcInput;
|
||||
if (convert_all)
|
||||
rcInput.partialPaymentAllowed = true;
|
||||
|
||||
auto rc = path::RippleCalc::rippleCalculate(
|
||||
*sandbox,
|
||||
saMaxAmount, // --> Amount to send is unlimited
|
||||
// to get an estimate.
|
||||
convert_all ? sa : saDstAmount, // --> Amount to deliver.
|
||||
raDst, // --> Account to deliver to.
|
||||
raSrc, // --> Account sending from.
|
||||
*result, // --> Path set.
|
||||
app.logs (),
|
||||
&rcInput);
|
||||
|
||||
JLOG (j.warning)
|
||||
<< "ripple_path_find:"
|
||||
<< " saMaxAmount=" << saMaxAmount
|
||||
<< " saDstAmount=" << saDstAmount
|
||||
<< " saMaxAmountAct=" << rc.actualAmountIn
|
||||
<< " saDstAmountAct=" << rc.actualAmountOut;
|
||||
|
||||
if (! convert_all &&
|
||||
! fullLiquidityPath.empty() &&
|
||||
(rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL))
|
||||
{
|
||||
auto jpr = app.journal ("PathRequest");
|
||||
JLOG (jpr.debug)
|
||||
<< "Trying with an extra path element";
|
||||
result->push_back(fullLiquidityPath);
|
||||
sandbox.emplace(&*cache->getLedger(), tapNONE);
|
||||
assert(sandbox->open());
|
||||
rc = path::RippleCalc::rippleCalculate(
|
||||
*sandbox,
|
||||
saMaxAmount, // --> Amount to send is unlimited
|
||||
// to get an estimate.
|
||||
saDstAmount, // --> Amount to deliver.
|
||||
raDst, // --> Account to deliver to.
|
||||
raSrc, // --> Account sending from.
|
||||
*result, // --> Path set.
|
||||
app.logs ());
|
||||
JLOG (jpr.debug)
|
||||
<< "Extra path element gives "
|
||||
<< transHuman(rc.result());
|
||||
}
|
||||
|
||||
if (rc.result() == tesSUCCESS)
|
||||
{
|
||||
Json::Value jvEntry(Json::objectValue);
|
||||
|
||||
STPathSet spsCanonical;
|
||||
|
||||
// Reuse the expanded as it would need to be calcuated
|
||||
// anyway to produce the canonical. (At least unless we
|
||||
// make a direct canonical.)
|
||||
|
||||
jvEntry[jss::source_amount] = rc.actualAmountIn.getJson(0);
|
||||
jvEntry[jss::paths_canonical] = Json::arrayValue;
|
||||
jvEntry[jss::paths_computed] = result->getJson(0);
|
||||
|
||||
if (convert_all)
|
||||
jvEntry[jss::destination_amount] = rc.actualAmountOut.getJson(0);
|
||||
|
||||
jvArray.append(jvEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
|
||||
transResultInfo(rc.result(), strToken, strHuman);
|
||||
|
||||
JLOG (j.debug)
|
||||
<< "ripple_path_find: "
|
||||
<< strToken << " "
|
||||
<< strHuman << " "
|
||||
<< spsComputed.getJson(0);
|
||||
}
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
transResultInfo(rc.result(), strToken, strHuman);
|
||||
JLOG (j.debug)
|
||||
<< "ripple_path_find: "
|
||||
<< strToken << " "
|
||||
<< strHuman << " "
|
||||
<< spsComputed.getJson(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/rpc/impl/TransactionSign.h>
|
||||
#include <ripple/app/ledger/LedgerMaster.h>
|
||||
#include <ripple/app/paths/FindPaths.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/paths/Pathfinder.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/core/LoadFeeTrack.h>
|
||||
#include <ripple/json/json_writer.h>
|
||||
@@ -192,33 +193,30 @@ static Json::Value checkPayment(
|
||||
if (!lpf.isOk ())
|
||||
return rpcError (rpcTOO_BUSY);
|
||||
|
||||
STPath fullLiquidityPath;
|
||||
auto cache = std::make_shared<RippleLineCache> (ledger);
|
||||
auto result = findPathsForOneIssuer (
|
||||
cache,
|
||||
srcAddressID,
|
||||
*dstAccountID,
|
||||
sendMax.issue(),
|
||||
amount,
|
||||
app.config().PATH_SEARCH_OLD,
|
||||
4, // iMaxPaths
|
||||
{},
|
||||
fullLiquidityPath,
|
||||
app);
|
||||
STPathSet result;
|
||||
if (ledger)
|
||||
{
|
||||
Pathfinder pf(std::make_shared<RippleLineCache>(ledger),
|
||||
srcAddressID, *dstAccountID, sendMax.issue().currency,
|
||||
sendMax.issue().account, amount, boost::none, app);
|
||||
if (pf.findPaths(app.config().PATH_SEARCH_OLD))
|
||||
{
|
||||
// 4 is the maxium paths
|
||||
pf.computePathRanks(4);
|
||||
STPath fullLiquidityPath;
|
||||
STPathSet paths;
|
||||
result = pf.getBestPaths(4, fullLiquidityPath, paths,
|
||||
sendMax.issue().account);
|
||||
}
|
||||
}
|
||||
|
||||
auto j = app.journal ("RPCHandler");
|
||||
if (! result)
|
||||
{
|
||||
JLOG (j.debug)
|
||||
<< "transactionSign: build_path: No paths found.";
|
||||
return rpcError (rpcNO_PATH);
|
||||
}
|
||||
JLOG (j.debug)
|
||||
<< "transactionSign: build_path: "
|
||||
<< result->getJson (0);
|
||||
<< result.getJson (0);
|
||||
|
||||
if (! result->empty ())
|
||||
tx_json[jss::Paths] = result->getJson (0);
|
||||
if (! result.empty ())
|
||||
tx_json[jss::Paths] = result.getJson (0);
|
||||
}
|
||||
}
|
||||
return Json::Value();
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <ripple/test/jtx/utility.h>
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/app/ledger/LedgerTiming.h>
|
||||
#include <ripple/app/paths/FindPaths.h>
|
||||
#include <ripple/app/paths/Pathfinder.h>
|
||||
#include <ripple/basics/Slice.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
@@ -87,7 +87,7 @@ Env::Env (beast::unit_test::suite& test_)
|
||||
, openLedger (closed_, app().config(), cachedSLEs_, journal)
|
||||
{
|
||||
memoize(master);
|
||||
initializePathfinding();
|
||||
Pathfinder::initPathTable();
|
||||
}
|
||||
|
||||
std::shared_ptr<ReadView const>
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/paths/Pathfinder.h>
|
||||
#include <ripple/test/jtx/paths.h>
|
||||
#include <ripple/app/paths/FindPaths.h>
|
||||
#include <ripple/protocol/JsonFields.h>
|
||||
|
||||
namespace ripple {
|
||||
@@ -36,16 +36,22 @@ paths::operator()(Env& env, JTx& jt) const
|
||||
jv[jss::Destination].asString());
|
||||
auto const amount = amountFromJson(
|
||||
sfAmount, jv[jss::Amount]);
|
||||
Pathfinder pf (
|
||||
std::make_shared<RippleLineCache>(env.open()),
|
||||
from, to, in_.currency, in_.account,
|
||||
amount, boost::none, env.app());
|
||||
if (! pf.findPaths(depth_))
|
||||
return;
|
||||
|
||||
STPath fp;
|
||||
auto const found = findPathsForOneIssuer(
|
||||
std::make_shared<RippleLineCache>(
|
||||
env.open()), from, to,
|
||||
in_, amount,
|
||||
depth_, limit_, {}, fp, env.app());
|
||||
pf.computePathRanks (limit_);
|
||||
auto const found = pf.getBestPaths(
|
||||
limit_, fp, {}, in_.account);
|
||||
|
||||
// VFALCO TODO API to allow caller to examine the STPathSet
|
||||
// VFALCO isDefault should be renamed to empty()
|
||||
if (found && ! found->isDefault())
|
||||
jv[jss::Paths] = found->getJson(0);
|
||||
if (! found.isDefault())
|
||||
jv[jss::Paths] = found.getJson(0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <ripple/app/paths/RippleState.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/Node.cpp>
|
||||
#include <ripple/app/paths/PathRequest.cpp>
|
||||
|
||||
Reference in New Issue
Block a user