From 20f186d85513e9c70e09bae7fc96f451022640d6 Mon Sep 17 00:00:00 2001 From: Miguel Portilla Date: Fri, 4 Sep 2015 19:02:00 -0400 Subject: [PATCH] Path find cleanup (RIPD-1023) --- src/ripple/app/main/Application.cpp | 4 +- src/ripple/app/paths/PathRequest.cpp | 267 +++++++++++---------- src/ripple/app/paths/PathRequest.h | 15 +- src/ripple/app/tests/Path_test.cpp | 10 +- src/ripple/rpc/RipplePathFind.h | 2 +- src/ripple/rpc/handlers/RipplePathFind.cpp | 247 +++++++++---------- src/ripple/rpc/impl/TransactionSign.cpp | 44 ++-- src/ripple/test/jtx/impl/Env.cpp | 4 +- src/ripple/test/jtx/impl/paths.cpp | 22 +- src/ripple/unity/app_paths.cpp | 1 - 10 files changed, 324 insertions(+), 292 deletions(-) diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index c5a1610fa..4701c16af 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include @@ -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); diff --git a/src/ripple/app/paths/PathRequest.cpp b/src/ripple/app/paths/PathRequest.cpp index 8a6ddb47e..9c7389aab 100644 --- a/src/ripple/app/paths/PathRequest.cpp +++ b/src/ripple/app/paths/PathRequest.cpp @@ -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 const& +PathRequest::getPathFinder(RippleLineCache::ref cache, + hash_map>& 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( + 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 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_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 + (&*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 + (&*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()) { diff --git a/src/ripple/app/paths/PathRequest.h b/src/ripple/app/paths/PathRequest.h index 79d5f8670..cf9e89788 100644 --- a/src/ripple/app/paths/PathRequest.h +++ b/src/ripple/app/paths/PathRequest.h @@ -21,7 +21,7 @@ #define RIPPLE_APP_PATHS_PATHREQUEST_H_INCLUDED #include -#include +#include #include #include #include @@ -98,10 +98,13 @@ private: void setValid (); void resetLevel (int level); - bool - findPaths (RippleLineCache::ref, - FindPaths&, Issue const&, - Json::Value& jvArray); + std::unique_ptr const& + getPathFinder(RippleLineCache::ref, + hash_map>&, 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 diff --git a/src/ripple/app/tests/Path_test.cpp b/src/ripple/app/tests/Path_test.cpp index e04a074dd..39be3d9c3 100644 --- a/src/ripple/app/tests/Path_test.cpp +++ b/src/ripple/app/tests/Path_test.cpp @@ -18,7 +18,6 @@ //============================================================================== #include -#include #include #include #include @@ -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"]; diff --git a/src/ripple/rpc/RipplePathFind.h b/src/ripple/rpc/RipplePathFind.h index 00fc4fc88..f1677ce92 100644 --- a/src/ripple/rpc/RipplePathFind.h +++ b/src/ripple/rpc/RipplePathFind.h @@ -31,7 +31,7 @@ ripplePathFind (RippleLineCache::pointer const& cache, STAmount const& saDstAmount, Json::Value const& jvSrcCurrencies, boost::optional const& contextPaths, - int const& level, boost::optional saSendMax, + int const level, boost::optional saSendMax, bool convert_all, Application& app); } diff --git a/src/ripple/rpc/handlers/RipplePathFind.cpp b/src/ripple/rpc/handlers/RipplePathFind.cpp index eda995974..8bca768fb 100644 --- a/src/ripple/rpc/handlers/RipplePathFind.cpp +++ b/src/ripple/rpc/handlers/RipplePathFind.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -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(context.params[jss::paths]) : boost::optional(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 const& +getPathFinder(RippleLineCache::ref 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 (RippleLineCache::pointer 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, + int const level, boost::optional 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_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 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 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); } } diff --git a/src/ripple/rpc/impl/TransactionSign.cpp b/src/ripple/rpc/impl/TransactionSign.cpp index b117afeb5..972013cf4 100644 --- a/src/ripple/rpc/impl/TransactionSign.cpp +++ b/src/ripple/rpc/impl/TransactionSign.cpp @@ -20,7 +20,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -192,33 +193,30 @@ static Json::Value checkPayment( if (!lpf.isOk ()) return rpcError (rpcTOO_BUSY); - STPath fullLiquidityPath; - auto cache = std::make_shared (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(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(); diff --git a/src/ripple/test/jtx/impl/Env.cpp b/src/ripple/test/jtx/impl/Env.cpp index 254c7178b..11e7918d7 100644 --- a/src/ripple/test/jtx/impl/Env.cpp +++ b/src/ripple/test/jtx/impl/Env.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -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 diff --git a/src/ripple/test/jtx/impl/paths.cpp b/src/ripple/test/jtx/impl/paths.cpp index 466bb4591..eac97d019 100644 --- a/src/ripple/test/jtx/impl/paths.cpp +++ b/src/ripple/test/jtx/impl/paths.cpp @@ -18,8 +18,8 @@ //============================================================================== #include +#include #include -#include #include 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(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( - 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); } //------------------------------------------------------------------------------ diff --git a/src/ripple/unity/app_paths.cpp b/src/ripple/unity/app_paths.cpp index 7f7fb3a20..f727fc738 100644 --- a/src/ripple/unity/app_paths.cpp +++ b/src/ripple/unity/app_paths.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include