From 1fe57720c47866deb6185598bfe5a249b545cfc8 Mon Sep 17 00:00:00 2001 From: David Schwartz Date: Wed, 19 Feb 2014 14:56:09 -0800 Subject: [PATCH] Legacy Pathfinding API improvements: * Use the cache for source/dest currencies * Allow a search depth and initial paths to be specified in old pathfinding --- src/ripple_app/paths/PathRequest.cpp | 13 ++++---- src/ripple_app/paths/PathRequest.h | 2 +- src/ripple_app/paths/Pathfinder.cpp | 35 +++++++++++++--------- src/ripple_app/paths/Pathfinder.h | 8 +++-- src/ripple_app/rpc/RPCHandler.cpp | 20 +++++++++++-- src/ripple_data/protocol/SerializedTypes.h | 18 +++++++++++ 6 files changed, 71 insertions(+), 25 deletions(-) diff --git a/src/ripple_app/paths/PathRequest.cpp b/src/ripple_app/paths/PathRequest.cpp index e24d5936a..ae5bab84f 100644 --- a/src/ripple_app/paths/PathRequest.cpp +++ b/src/ripple_app/paths/PathRequest.cpp @@ -110,14 +110,15 @@ bool PathRequest::needsUpdate (bool newOnly, LedgerIndex index) } } -bool PathRequest::isValid (Ledger::ref lrLedger) +bool PathRequest::isValid (RippleLineCache::ref crCache) { ScopedLockType sl (mLock, __FILE__, __LINE__); bValid = raSrcAccount.isSet () && raDstAccount.isSet () && saDstAmount.isPositive (); + Ledger::pointer lrLedger = crCache->getLedger (); if (bValid) { - AccountState::pointer asSrc = getApp().getOPs ().getAccountState (lrLedger, raSrcAccount); + AccountState::pointer asSrc = getApp().getOPs ().getAccountState (crCache->getLedger(), raSrcAccount); if (!asSrc) { @@ -153,7 +154,7 @@ bool PathRequest::isValid (Ledger::ref lrLedger) { bool includeXRP = !isSetBit (asDst->peekSLE ().getFlags(), lsfDisallowXRP); boost::unordered_set usDestCurrID = - usAccountDestCurrencies (raDstAccount, lrLedger, includeXRP); + usAccountDestCurrencies (raDstAccount, crCache, includeXRP); BOOST_FOREACH (const uint160 & uCurrency, usDestCurrID) jvDestCur.append (STAmount::createHumanCurrency (uCurrency)); @@ -179,7 +180,7 @@ Json::Value PathRequest::doCreate (Ledger::ref lrLedger, RippleLineCache::ref& c if (parseJson (value, true) != PFR_PJ_INVALID) { - bValid = isValid (lrLedger); + bValid = isValid (cache); if (bValid) status = doUpdate (cache, true); @@ -324,7 +325,7 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast) ScopedLockType sl (mLock, __FILE__, __LINE__); - if (!isValid (cache->getLedger ())) + if (!isValid (cache)) return jvStatus; jvStatus = Json::objectValue; @@ -333,7 +334,7 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast) if (sourceCurrencies.empty ()) { boost::unordered_set usCurrencies = - usAccountSourceCurrencies (raSrcAccount, cache->getLedger (), true); + usAccountSourceCurrencies (raSrcAccount, cache, true); bool sameAccount = raSrcAccount == raDstAccount; BOOST_FOREACH (const uint160 & c, usCurrencies) { diff --git a/src/ripple_app/paths/PathRequest.h b/src/ripple_app/paths/PathRequest.h index f1ea4cec8..0ec522473 100644 --- a/src/ripple_app/paths/PathRequest.h +++ b/src/ripple_app/paths/PathRequest.h @@ -51,7 +51,7 @@ public: ~PathRequest (); - bool isValid (const boost::shared_ptr&); + bool isValid (RippleLineCache::ref crCache); bool isValid (); bool isNew (); bool needsUpdate (bool newOnly, LedgerIndex index); diff --git a/src/ripple_app/paths/Pathfinder.cpp b/src/ripple_app/paths/Pathfinder.cpp index 15c3bee13..cbb68bc30 100644 --- a/src/ripple_app/paths/Pathfinder.cpp +++ b/src/ripple_app/paths/Pathfinder.cpp @@ -202,16 +202,19 @@ bool Pathfinder::findPaths (int iLevel, const unsigned int iMaxPaths, STPathSet& BOOST_FOREACH(const STPath& path, pathsOut) { // make sure no paths were lost bool found = false; - BOOST_FOREACH(const STPath& ePath, mCompletePaths) + if (!path.isEmpty ()) { - if (ePath == path) + BOOST_FOREACH(const STPath& ePath, mCompletePaths) { - found = true; - break; + if (ePath == path) + { + found = true; + break; + } } + if (!found) + mCompletePaths.addPath(path); } - if (!found) - mCompletePaths.addPath(path); } WriteLog (lsDEBUG, Pathfinder) << mCompletePaths.size() << " paths to filter"; @@ -385,7 +388,8 @@ STPathSet Pathfinder::filterPaths(int iMaxPaths, STPath& extraPath) return spsDst; } -boost::unordered_set usAccountSourceCurrencies (const RippleAddress& raAccountID, Ledger::ref lrLedger, +boost::unordered_set usAccountSourceCurrencies ( + const RippleAddress& raAccountID, RippleLineCache::ref lrCache, bool includeXRP) { boost::unordered_set usCurrencies; @@ -395,7 +399,7 @@ boost::unordered_set usAccountSourceCurrencies (const RippleAddress& ra usCurrencies.insert (uint160 (CURRENCY_XRP)); // List of ripple lines. - AccountItems rippleLines (raAccountID.getAccountID (), lrLedger, AccountItem::pointer (new RippleState ())); + AccountItems& rippleLines (lrCache->getRippleLines (raAccountID.getAccountID ())); BOOST_FOREACH (AccountItem::ref item, rippleLines.getItems ()) { @@ -415,7 +419,9 @@ boost::unordered_set usAccountSourceCurrencies (const RippleAddress& ra return usCurrencies; } -boost::unordered_set usAccountDestCurrencies (const RippleAddress& raAccountID, Ledger::ref lrLedger, +boost::unordered_set usAccountDestCurrencies ( + const RippleAddress& raAccountID, + RippleLineCache::ref lrCache, bool includeXRP) { boost::unordered_set usCurrencies; @@ -424,7 +430,7 @@ boost::unordered_set usAccountDestCurrencies (const RippleAddress& raAc usCurrencies.insert (uint160 (CURRENCY_XRP)); // Even if account doesn't exist // List of ripple lines. - AccountItems rippleLines (raAccountID.getAccountID (), lrLedger, AccountItem::pointer (new RippleState ())); + AccountItems& rippleLines (lrCache->getRippleLines (raAccountID.getAccountID ())); BOOST_FOREACH (AccountItem::ref item, rippleLines.getItems ()) { @@ -474,6 +480,7 @@ int Pathfinder::getPathsOut (RippleCurrency const& currencyID, const uint160& ac int count = 0; AccountItems& rippleLines (mRLCache->getRippleLines (accountID)); + BOOST_FOREACH (AccountItem::ref item, rippleLines.getItems ()) { RippleState* rspEntry = (RippleState*) item.get (); @@ -635,7 +642,7 @@ void Pathfinder::addLink( bool const bIsEndCurrency = (uEndCurrency == mDstAmount.getCurrency()); bool const bIsNoRippleOut = isNoRippleOut (currentPath); - AccountItems& rippleLines(mRLCache->getRippleLines(uEndAccount)); + AccountItems& rippleLines (mRLCache->getRippleLines(uEndAccount)); std::vector< std::pair > candidates; candidates.reserve(rippleLines.getItems().size()); @@ -866,7 +873,7 @@ void Pathfinder::initPathTable() { // XRP to non-XRP CostedPathList_t& list = mPathTable[pt_XRP_to_nonXRP]; - list.push_back(CostedPath_t(0, makePath("sfd"))); // source -> book -> gateway + list.push_back(CostedPath_t(1, makePath("sfd"))); // source -> book -> gateway list.push_back(CostedPath_t(3, makePath("sfad"))); // source -> book -> account -> destination list.push_back(CostedPath_t(5, makePath("sfaad"))); // source -> book -> account -> account -> destination list.push_back(CostedPath_t(6, makePath("sbfd"))); // source -> book -> book -> destination @@ -878,8 +885,8 @@ void Pathfinder::initPathTable() { // non-XRP to XRP CostedPathList_t& list = mPathTable[pt_nonXRP_to_XRP]; - list.push_back(CostedPath_t(0, makePath("sxd"))); // gateway buys XRP - list.push_back(CostedPath_t(1, makePath("saxd"))); // source -> gateway -> book(XRP) -> dest + list.push_back(CostedPath_t(1, makePath("sxd"))); // gateway buys XRP + list.push_back(CostedPath_t(2, makePath("saxd"))); // source -> gateway -> book(XRP) -> dest list.push_back(CostedPath_t(6, makePath("saaxd"))); list.push_back(CostedPath_t(7, makePath("sbxd"))); list.push_back(CostedPath_t(8, makePath("sabxd"))); diff --git a/src/ripple_app/paths/Pathfinder.h b/src/ripple_app/paths/Pathfinder.h index 99030c5c9..ae893411d 100644 --- a/src/ripple_app/paths/Pathfinder.h +++ b/src/ripple_app/paths/Pathfinder.h @@ -136,10 +136,14 @@ private: static const uint32 afAC_LAST = 0x080; // Destination account only }; -boost::unordered_set usAccountDestCurrencies (const RippleAddress& raAccountID, Ledger::ref lrLedger, +boost::unordered_set usAccountDestCurrencies + (const RippleAddress& raAccountID, + RippleLineCache::ref cache, bool includeXRP); -boost::unordered_set usAccountSourceCurrencies (const RippleAddress& raAccountID, Ledger::ref lrLedger, +boost::unordered_set usAccountSourceCurrencies + (const RippleAddress& raAccountID, + RippleLineCache::ref lrLedger, bool includeXRP); #endif diff --git a/src/ripple_app/rpc/RPCHandler.cpp b/src/ripple_app/rpc/RPCHandler.cpp index 19e8d78ef..856395054 100644 --- a/src/ripple_app/rpc/RPCHandler.cpp +++ b/src/ripple_app/rpc/RPCHandler.cpp @@ -1780,7 +1780,7 @@ Json::Value RPCHandler::doRipplePathFind (Json::Value params, Resource::Charge& } else { - boost::unordered_set usCurrencies = usAccountSourceCurrencies (raSrc, lpLedger, true); + boost::unordered_set usCurrencies = usAccountSourceCurrencies (raSrc, cache, true); jvSrcCurrencies = Json::Value (Json::arrayValue); @@ -1797,7 +1797,7 @@ Json::Value RPCHandler::doRipplePathFind (Json::Value params, Resource::Charge& // Fill in currencies destination will accept Json::Value jvDestCur (Json::arrayValue); - boost::unordered_set usDestCurrID = usAccountDestCurrencies (raDst, lpLedger, true); + boost::unordered_set usDestCurrID = usAccountDestCurrencies (raDst, cache, true); BOOST_FOREACH (const uint160 & uCurrency, usDestCurrID) jvDestCur.append (STAmount::createHumanCurrency (uCurrency)); @@ -1847,6 +1847,22 @@ Json::Value RPCHandler::doRipplePathFind (Json::Value params, Resource::Charge& int level = getConfig().PATH_SEARCH_OLD; if ((getConfig().PATH_SEARCH_MAX > level) && !getApp().getFeeTrack().isLoadedLocal()) ++level; + if (params.isMember("depth") && params["depth"].isIntegral()) + { + int rLev = params["search_depth"].asInt (); + if ((rLev < level) || (mRole == Config::ADMIN)) + level = rLev; + } + + if (params.isMember("paths")) + { + STParsedJSON paths ("paths", params["paths"]); + if (paths.object.get() == nullptr) + return paths.error; + else + spsComputed = paths.object.get()->downcast (); + } + STPath extraPath; if (!bValid || !pf.findPaths (level, 4, spsComputed, extraPath)) { diff --git a/src/ripple_data/protocol/SerializedTypes.h b/src/ripple_data/protocol/SerializedTypes.h index f31b88477..7fcd3d684 100644 --- a/src/ripple_data/protocol/SerializedTypes.h +++ b/src/ripple_data/protocol/SerializedTypes.h @@ -166,6 +166,24 @@ public: return true; } + template + D& downcast() + { + D* ptr = dynamic_cast (this); + if (ptr == nullptr) + throw std::runtime_error ("type mismatch"); + return *ptr; + } + + template + D const& downcast() const + { + D const * ptr = dynamic_cast (this); + if (ptr == nullptr) + throw std::runtime_error ("type mismatch"); + return *ptr; + } + protected: // VFALCO TODO make accessors for this SField::ptr fName;