diff --git a/Builds/VisualStudio2015/RippleD.vcxproj b/Builds/VisualStudio2015/RippleD.vcxproj
index 8944f2dc30..4e0cef95be 100644
--- a/Builds/VisualStudio2015/RippleD.vcxproj
+++ b/Builds/VisualStudio2015/RippleD.vcxproj
@@ -3355,8 +3355,6 @@
-
-
diff --git a/Builds/VisualStudio2015/RippleD.vcxproj.filters b/Builds/VisualStudio2015/RippleD.vcxproj.filters
index 5a2880c876..429e3f8e0c 100644
--- a/Builds/VisualStudio2015/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2015/RippleD.vcxproj.filters
@@ -3813,9 +3813,6 @@
ripple\rpc
-
- ripple\rpc
-
ripple\rpc
diff --git a/src/ripple/app/paths/PathRequest.h b/src/ripple/app/paths/PathRequest.h
index 372cbe5679..4d2fa1ecf7 100644
--- a/src/ripple/app/paths/PathRequest.h
+++ b/src/ripple/app/paths/PathRequest.h
@@ -59,6 +59,9 @@ public:
public:
// VFALCO TODO Break the cyclic dependency on InfoSub
+
+ // path_find semantics
+ // Subscriber is updated
PathRequest (
Application& app,
std::shared_ptr const& subscriber,
@@ -66,6 +69,8 @@ public:
PathRequests&,
beast::Journal journal);
+ // ripple_path_find semantics
+ // Completion function is called
PathRequest (
Application& app,
std::function const& completion,
diff --git a/src/ripple/app/paths/PathRequests.cpp b/src/ripple/app/paths/PathRequests.cpp
index fc57364095..14726d364e 100644
--- a/src/ripple/app/paths/PathRequests.cpp
+++ b/src/ripple/app/paths/PathRequests.cpp
@@ -218,7 +218,7 @@ PathRequests::makePathRequest(
insertPathRequest (req);
app_.getLedgerMaster().newPathRequest();
}
- return result.second;
+ return std::move (result.second);
}
// Make an old-style ripple_path_find request
@@ -249,7 +249,24 @@ PathRequests::makeLegacyPathRequest(
app_.getLedgerMaster().newPathRequest();
}
- return result.second;
+ return std::move (result.second);
+}
+
+Json::Value
+PathRequests::doLegacyPathRequest (
+ Resource::Consumer& consumer,
+ std::shared_ptr const& inLedger,
+ Json::Value const& request)
+{
+ auto cache = std::make_shared (inLedger);
+
+ auto req = std::make_shared (app_, []{},
+ consumer, ++mLastIdentifier, *this, mJournal);
+
+ auto result = req->doCreate (cache, request);
+ if (result.first)
+ result.second = req->doUpdate (cache, false);
+ return std::move (result.second);
}
} // ripple
diff --git a/src/ripple/app/paths/PathRequests.h b/src/ripple/app/paths/PathRequests.h
index eb8749d2f4..c8359566fb 100644
--- a/src/ripple/app/paths/PathRequests.h
+++ b/src/ripple/app/paths/PathRequests.h
@@ -49,11 +49,16 @@ public:
std::shared_ptr getLineCache (
std::shared_ptr const& ledger, bool authoritative);
+ // Create a new-style path request that pushes
+ // updates to a subscriber
Json::Value makePathRequest (
std::shared_ptr const& subscriber,
std::shared_ptr const& ledger,
Json::Value const& request);
+ // Create an old-style path request that is
+ // managed by a coroutine and updated by
+ // the path engine
Json::Value makeLegacyPathRequest (
PathRequest::pointer& req,
std::function completion,
@@ -61,6 +66,13 @@ public:
std::shared_ptr const& inLedger,
Json::Value const& request);
+ // Execute an old-style path request immediately
+ // with the ledger specified by the caller
+ Json::Value doLegacyPathRequest (
+ Resource::Consumer& consumer,
+ std::shared_ptr const& inLedger,
+ Json::Value const& request);
+
void reportFast (std::chrono::milliseconds ms)
{
mFast.notify (ms);
diff --git a/src/ripple/app/tests/Path_test.cpp b/src/ripple/app/tests/Path_test.cpp
index 3cf14e05c5..f4a562e329 100644
--- a/src/ripple/app/tests/Path_test.cpp
+++ b/src/ripple/app/tests/Path_test.cpp
@@ -29,7 +29,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -143,52 +142,6 @@ equal(STAmount const& sa1, STAmount const& sa2)
sa1.issue().account == sa2.issue().account;
}
-std::tuple
-find_paths(jtx::Env& env,
- jtx::Account const& src, jtx::Account const& dst,
- STAmount const& saDstAmount,
- boost::optional const& saSendMax = boost::none)
-{
- static int const level = 8;
- auto const& view = env.current();
- auto cache = std::make_shared(view);
- auto currencies = accountSourceCurrencies(src, cache, true);
- auto jvSrcCurrencies = Json::Value(Json::arrayValue);
- for (auto const& c : currencies)
- {
- Json::Value jvCurrency = Json::objectValue;
- 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(),
- (convert_all ? STAmount(saDstAmount.issue(), STAmount::cMaxValue,
- STAmount::cMaxOffset) : saDstAmount), jvSrcCurrencies, boost::none,
- level, saSendMax, convert_all, env.app());
- if (! result.first)
- {
- Throw (
- "Path_test::findPath: ripplePathFind find failed");
- }
- auto const& jv = result.second[0u];
- Json::Value paths;
- paths["Paths"] = jv["paths_computed"];
- STParsedJSONObject stp("generic", paths);
-
- STAmount sa;
- if (jv.isMember(jss::source_amount))
- sa = amountFromJson(sfGeneric, jv[jss::source_amount]);
-
- STAmount da;
- if (jv.isMember(jss::destination_amount))
- da = amountFromJson(sfGeneric, jv[jss::destination_amount]);
-
- return std::make_tuple(
- std::move(stp.object->getFieldPathSet(sfPaths)),
- std::move(sa), std::move(da));
-}
-
Json::Value
rpf(jtx::Account const& src, jtx::Account const& dst, std::uint32_t num_src)
{
@@ -252,6 +205,79 @@ public:
}
};
+ std::tuple
+ find_paths(jtx::Env& env,
+ jtx::Account const& src, jtx::Account const& dst,
+ STAmount const& saDstAmount,
+ boost::optional const& saSendMax = boost::none)
+ {
+ using namespace jtx;
+
+ auto& app = env.app();
+ Resource::Charge loadType = Resource::feeReferenceRPC;
+ Resource::Consumer c;
+ RPC::Context context {beast::Journal(), {}, app, loadType,
+ app.getOPs(), app.getLedgerMaster(), c, Role::USER, {}};
+
+ Json::Value params = Json::objectValue;
+ params[jss::command] = "ripple_path_find";
+ params[jss::source_account] = toBase58 (src);
+ params[jss::destination_account] = toBase58 (dst);
+ params[jss::destination_amount] = saDstAmount.getJson(0);
+ if (saSendMax)
+ params[jss::send_max] = saSendMax->getJson(0);
+
+ Json::Value result;
+ gate g;
+ app.getJobQueue().postCoro(jtCLIENT, "RPC-Client",
+ [&](auto const& coro)
+ {
+ context.params = std::move (params);
+ context.jobCoro = coro;
+ RPC::doCommand (context, result);
+ g.signal();
+ });
+
+ BEAST_EXPECT(g.wait_for(5s));
+ BEAST_EXPECT(! result.isMember(jss::error));
+
+ STAmount da;
+ if (result.isMember(jss::destination_amount))
+ da = amountFromJson(sfGeneric,
+ result[jss::destination_amount]);
+
+ STAmount sa;
+ STPathSet paths;
+ if (result.isMember(jss::alternatives))
+ {
+ auto const& alts = result[jss::alternatives];
+ if (alts.size() > 0)
+ {
+ auto const& path = alts[0u];
+
+ if (path.isMember(jss::source_amount))
+ sa = amountFromJson(sfGeneric,
+ path[jss::source_amount]);
+
+
+ if (path.isMember(jss::destination_amount))
+ da = amountFromJson(sfGeneric,
+ path[jss::destination_amount]);
+
+ if (path.isMember(jss::paths_computed))
+ {
+ Json::Value p;
+ p["Paths"] = path[jss::paths_computed];
+ STParsedJSONObject po("generic", p);
+ paths = po.object->getFieldPathSet (sfPaths);
+ }
+ }
+ }
+
+ return std::make_tuple(
+ std::move(paths), std::move(sa), std::move(da));
+ }
+
void
source_currencies_limit()
{
diff --git a/src/ripple/resource/impl/Consumer.cpp b/src/ripple/resource/impl/Consumer.cpp
index cd8654a97f..45eaae2683 100644
--- a/src/ripple/resource/impl/Consumer.cpp
+++ b/src/ripple/resource/impl/Consumer.cpp
@@ -98,8 +98,12 @@ Disposition Consumer::disposition() const
Disposition Consumer::charge (Charge const& what)
{
- assert (m_entry != nullptr);
- return m_logic->charge (*m_entry, what);
+ Disposition d = ok;
+
+ if (m_logic && m_entry)
+ d = m_logic->charge (*m_entry, what);
+
+ return d;
}
bool Consumer::warn ()
diff --git a/src/ripple/rpc/RipplePathFind.h b/src/ripple/rpc/RipplePathFind.h
deleted file mode 100644
index 4e23843d59..0000000000
--- a/src/ripple/rpc/RipplePathFind.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of rippled: https://github.com/ripple/rippled
- Copyright (c) 2015 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 RIPPLE_RPC_RIPPLEPATHFIND_H_INCLUDED
-#define RIPPLE_RPC_RIPPLEPATHFIND_H_INCLUDED
-
-#include
-#include
-
-namespace ripple {
-
-std::pair
-ripplePathFind (std::shared_ptr const& cache,
- AccountID const& raSrc, AccountID const& raDst,
- STAmount const& saDstAmount,
- Json::Value const& jvSrcCurrencies,
- boost::optional const& contextPaths,
- int const level, boost::optional saSendMax,
- bool convert_all, Application& app);
-
-}
-
-#endif
diff --git a/src/ripple/rpc/handlers/RipplePathFind.cpp b/src/ripple/rpc/handlers/RipplePathFind.cpp
index dc1b30ceac..c3998262fc 100644
--- a/src/ripple/rpc/handlers/RipplePathFind.cpp
+++ b/src/ripple/rpc/handlers/RipplePathFind.cpp
@@ -18,7 +18,6 @@
//==============================================================================
#include
-#include
#include
#include
#include
@@ -39,7 +38,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -65,6 +63,8 @@ Json::Value doRipplePathFind (RPC::Context& context)
! context.params.isMember(jss::ledger_index) &&
! context.params.isMember(jss::ledger_hash))
{
+ // No ledger specified, use pathfinding defaults
+ // and dispatch to pathfinding engine
if (context.app.getLedgerMaster().getValidatedLedgerAge() >
RPC::Tuning::maxValidatedLedgerAge)
{
@@ -95,380 +95,13 @@ Json::Value doRipplePathFind (RPC::Context& context)
if (! lpf.isOk ())
return rpcError (rpcTOO_BUSY);
- AccountID raSrc;
- AccountID raDst;
- STAmount saDstAmount;
- if (! context.params.isMember (jss::source_account))
- {
- jvResult = rpcError (rpcSRC_ACT_MISSING);
- }
- else if (! deprecatedParseBase58(raSrc,
- context.params[jss::source_account]))
- {
- jvResult = rpcError (rpcSRC_ACT_MALFORMED);
- }
- else if (!context.params.isMember (jss::destination_account))
- {
- jvResult = rpcError (rpcDST_ACT_MISSING);
- }
- else if (! deprecatedParseBase58 (raDst,
- context.params[jss::destination_account]))
- {
- jvResult = rpcError (rpcDST_ACT_MALFORMED);
- }
- else if (
- // Parse saDstAmount.
- !context.params.isMember (jss::destination_amount)
- || ! amountFromJsonNoThrow(saDstAmount, context.params[jss::destination_amount])
- || (saDstAmount <= zero && saDstAmount !=
- STAmount(saDstAmount.issue(), 1u, 0, true))
- || (!isXRP(saDstAmount.getCurrency ())
- && (!saDstAmount.getIssuer () ||
- noAccount() == saDstAmount.getIssuer ())))
- {
- JLOG (context.j.info()) << "Bad destination_amount.";
- jvResult = rpcError (rpcINVALID_PARAMS);
- }
- else if (
- // Checks on source_currencies.
- context.params.isMember(jss::source_currencies) &&
- (! context.params[jss::source_currencies].isArray() ||
- context.params[jss::source_currencies].size() == 0 ||
- context.params[jss::source_currencies].size() >
- RPC::Tuning::max_src_cur))
- {
- JLOG (context.j.info()) << "Bad source_currencies.";
- jvResult = rpcError(rpcINVALID_PARAMS);
- }
- else
- {
- std::shared_ptr cache;
+ auto result = context.app.getPathRequests().doLegacyPathRequest (
+ context.consumer, lpLedger, context.params);
- if (lpLedger)
- {
- // The caller specified a ledger
- cache = std::make_shared(lpLedger);
- }
- else
- {
- // The closed ledger is recent and any nodes made resident
- // have the best chance to persist
- lpLedger = context.ledgerMaster.getClosedLedger();
- cache = context.app.getPathRequests().getLineCache(lpLedger, false);
- }
+ for (auto &fieldName : jvResult.getMemberNames ())
+ result[fieldName] = std::move (jvResult[fieldName]);
- Json::Value jvSrcCurrencies;
- if (context.params.isMember (jss::source_currencies))
- {
- jvSrcCurrencies = context.params[jss::source_currencies];
- }
- else
- {
- auto currencies = accountSourceCurrencies(raSrc, cache, true);
- if (currencies.size() > RPC::Tuning::max_auto_src_cur)
- return rpcError(rpcINTERNAL);
- auto jvSrcCurrencies = Json::Value(Json::arrayValue);
- for (auto const& c : currencies)
- {
- Json::Value jvCurrency(Json::objectValue);
- jvCurrency[jss::currency] = to_string(c);
- jvSrcCurrencies.append(jvCurrency);
- }
- }
-
- // Fill in currencies destination will accept
- Json::Value jvDestCur (Json::arrayValue);
-
- // TODO(tom): this could be optimized the same way that
- // PathRequest::doUpdate() is - if we don't obsolete this code first.
- auto usDestCurrID = accountDestCurrencies (raDst, cache, true);
- for (auto const& uCurrency: usDestCurrID)
- jvDestCur.append (to_string (uCurrency));
-
- jvResult[jss::destination_currencies] = jvDestCur;
- jvResult[jss::destination_account] = context.app.accountIDCache().toBase58(raDst);
-
- int level = context.app.config().PATH_SEARCH_OLD;
- if ((context.app.config().PATH_SEARCH_MAX > level)
- && !context.app.getFeeTrack().isLoadedLocal())
- {
- ++level;
- }
-
- if (context.params.isMember(jss::search_depth)
- && context.params[jss::search_depth].isIntegral())
- {
- int rLev = context.params[jss::search_depth].asInt ();
- if ((rLev < level) || (isUnlimited (context.role)))
- level = rLev;
- }
-
- auto const convert_all =
- saDstAmount == STAmount(saDstAmount.issue(), 1u, 0, true);
-
- boost::optional saSendMax;
- if (context.params.isMember(jss::send_max))
- {
- // Send_max requires destination amount to be -1.
- if (! convert_all)
- return rpcError(rpcDST_AMT_MALFORMED);
-
- saSendMax.emplace();
- if (!amountFromJsonNoThrow(
- *saSendMax, context.params[jss::send_max]) ||
- (saSendMax->getCurrency().isZero() &&
- saSendMax->getIssuer().isNonZero()) ||
- (saSendMax->getCurrency() == badCurrency()) ||
- (*saSendMax <= zero &&
- *saSendMax != STAmount(saSendMax->issue(), 1u, 0, true)))
- {
- return rpcError(rpcSENDMAX_MALFORMED);
- }
- }
-
- auto contextPaths = context.params.isMember(jss::paths) ?
- boost::optional(context.params[jss::paths]) :
- boost::optional(boost::none);
- 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;
-
- // Each alternative differs by source currency.
- jvResult[jss::alternatives] = pathFindResult.second;
- }
-
- JLOG (context.j.debug())
- << "ripple_path_find< " << jvResult;
-
- return jvResult;
-}
-
-std::unique_ptr const&
-getPathFinder(std::shared_ptr const& cache, AccountID const& raSrc,
- AccountID const& raDst, boost::optional saSendMax,
- hash_map>& 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(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
-ripplePathFind (std::shared_ptr const& cache,
- AccountID const& raSrc, AccountID const& raDst,
- STAmount const& saDstAmount, Json::Value const& jvSrcCurrencies,
- boost::optional const& contextPaths,
- int const level, boost::optional saSendMax,
- bool convert_all, Application& app)
-{
- Json::Value jvArray(Json::arrayValue);
- hash_map> currency_map;
-
- auto j = app.journal ("RPCHandler");
-
- for (auto const& c : jvSrcCurrencies)
- {
- if (! c.isObject())
- return std::make_pair(false, rpcError(rpcINVALID_PARAMS));
-
- // Mandatory currency
- Currency srcCurrencyID;
- if (! c.isMember(jss::currency) ||
- ! to_currency(srcCurrencyID, c[jss::currency].asString()))
- {
- JLOG (j.info()) << "Bad currency.";
- return std::make_pair(false, rpcError(rpcSRC_CUR_MALFORMED));
- }
-
- // Optional issuer
- AccountID srcIssuerID;
- if (c.isMember (jss::issuer) &&
- (! c[jss::issuer].isString() ||
- ! to_issuer(srcIssuerID, c[jss::issuer].asString()) ||
- srcIssuerID.isZero() != srcCurrencyID.isZero() ||
- noAccount() == srcIssuerID))
- {
- JLOG (j.info()) << "Bad issuer.";
- return std::make_pair(false, rpcError(rpcSRC_ISR_MALFORMED));
- }
-
- if (srcIssuerID.isZero())
- srcIssuerID = raSrc;
-
- auto issue = Issue(srcCurrencyID, srcIssuerID);
- if (saSendMax)
- {
- // If the currencies don't match, ignore the source currency.
- if (srcCurrencyID != saSendMax->getCurrency())
- continue;
-
- // If neither is the source and they are not equal, then the
- // source issuer is illegal.
- if (srcIssuerID != raSrc && saSendMax->getIssuer() != raSrc &&
- srcIssuerID != saSendMax->getIssuer())
- {
- return std::make_pair(false, rpcError(rpcSRC_ISR_MALFORMED));
- }
-
- // If both are the source, use the source.
- // Otherwise, use the one that's not the source.
- if (srcIssuerID == raSrc)
- {
- issue.account = saSendMax->getIssuer() != raSrc ?
- saSendMax->getIssuer() : raSrc;
- }
- }
-
- STPathSet spsComputed;
- if (contextPaths)
- {
- Json::Value pathSet = Json::objectValue;
- pathSet[jss::Paths] = contextPaths.get();
- STParsedJSONObject paths("pathSet", pathSet);
- if (! paths.object)
- return std::make_pair(false, paths.error);
-
- 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.warn()) << "ripple_path_find: No paths found.";
- continue;
- }
-
- STPath fullLiquidityPath;
- auto ps = pathfinder->getBestPaths(max_paths,
- fullLiquidityPath, spsComputed, issue.account);
-
- STAmount saMaxAmount;
- if (saSendMax)
- {
- saMaxAmount = *saSendMax;
- }
- else
- {
- AccountID issuerID;
- if (isXRP(srcIssuerID))
- {
- // Default to source account.
- if(isXRP(srcCurrencyID))
- issuerID = xrpAccount();
- else
- issuerID = raSrc;
- }
- else
- {
- // Use specifed issuer.
- issuerID = srcIssuerID;
- }
-
- saMaxAmount = STAmount(
- {srcCurrencyID, issuerID}, 1u, 0, true);
- }
-
- boost::optional 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(),
- app.config(),
- &rcInput);
-
- JLOG(j.info())
- << "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";
- 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(),
- app.config());
- 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
- {
- std::string strToken;
- std::string strHuman;
- transResultInfo(rc.result(), strToken, strHuman);
- JLOG (j.debug())
- << "ripple_path_find: "
- << strToken << " "
- << strHuman << " "
- << spsComputed.getJson(0);
- }
- }
-
- return std::make_pair(true, std::move(jvArray));
+ return result;
}
} // ripple