Legacy Pathfinding API improvements:

* Use the cache for source/dest currencies
* Allow a search depth and initial paths to be specified in old pathfinding
This commit is contained in:
David Schwartz
2014-02-19 14:56:09 -08:00
committed by Vinnie Falco
parent fca8fa1b1b
commit 1fe57720c4
6 changed files with 71 additions and 25 deletions

View File

@@ -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<uint160> 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<uint160> usCurrencies =
usAccountSourceCurrencies (raSrcAccount, cache->getLedger (), true);
usAccountSourceCurrencies (raSrcAccount, cache, true);
bool sameAccount = raSrcAccount == raDstAccount;
BOOST_FOREACH (const uint160 & c, usCurrencies)
{

View File

@@ -51,7 +51,7 @@ public:
~PathRequest ();
bool isValid (const boost::shared_ptr<Ledger>&);
bool isValid (RippleLineCache::ref crCache);
bool isValid ();
bool isNew ();
bool needsUpdate (bool newOnly, LedgerIndex index);

View File

@@ -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<uint160> usAccountSourceCurrencies (const RippleAddress& raAccountID, Ledger::ref lrLedger,
boost::unordered_set<uint160> usAccountSourceCurrencies (
const RippleAddress& raAccountID, RippleLineCache::ref lrCache,
bool includeXRP)
{
boost::unordered_set<uint160> usCurrencies;
@@ -395,7 +399,7 @@ boost::unordered_set<uint160> 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<uint160> usAccountSourceCurrencies (const RippleAddress& ra
return usCurrencies;
}
boost::unordered_set<uint160> usAccountDestCurrencies (const RippleAddress& raAccountID, Ledger::ref lrLedger,
boost::unordered_set<uint160> usAccountDestCurrencies (
const RippleAddress& raAccountID,
RippleLineCache::ref lrCache,
bool includeXRP)
{
boost::unordered_set<uint160> usCurrencies;
@@ -424,7 +430,7 @@ boost::unordered_set<uint160> 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<int, uint160> > 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")));

View File

@@ -136,10 +136,14 @@ private:
static const uint32 afAC_LAST = 0x080; // Destination account only
};
boost::unordered_set<uint160> usAccountDestCurrencies (const RippleAddress& raAccountID, Ledger::ref lrLedger,
boost::unordered_set<uint160> usAccountDestCurrencies
(const RippleAddress& raAccountID,
RippleLineCache::ref cache,
bool includeXRP);
boost::unordered_set<uint160> usAccountSourceCurrencies (const RippleAddress& raAccountID, Ledger::ref lrLedger,
boost::unordered_set<uint160> usAccountSourceCurrencies
(const RippleAddress& raAccountID,
RippleLineCache::ref lrLedger,
bool includeXRP);
#endif

View File

@@ -1780,7 +1780,7 @@ Json::Value RPCHandler::doRipplePathFind (Json::Value params, Resource::Charge&
}
else
{
boost::unordered_set<uint160> usCurrencies = usAccountSourceCurrencies (raSrc, lpLedger, true);
boost::unordered_set<uint160> 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<uint160> usDestCurrID = usAccountDestCurrencies (raDst, lpLedger, true);
boost::unordered_set<uint160> 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<STPathSet> ();
}
STPath extraPath;
if (!bValid || !pf.findPaths (level, 4, spsComputed, extraPath))
{

View File

@@ -166,6 +166,24 @@ public:
return true;
}
template <class D>
D& downcast()
{
D* ptr = dynamic_cast<D*> (this);
if (ptr == nullptr)
throw std::runtime_error ("type mismatch");
return *ptr;
}
template <class D>
D const& downcast() const
{
D const * ptr = dynamic_cast<D const*> (this);
if (ptr == nullptr)
throw std::runtime_error ("type mismatch");
return *ptr;
}
protected:
// VFALCO TODO make accessors for this
SField::ptr fName;