From 01f1e6c33759ea0caeee1427d21e6ed9f09736ee Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Wed, 5 Dec 2012 18:02:24 -0800 Subject: [PATCH] Work on path finding. --- src/cpp/ripple/Pathfinder.cpp | 74 ++++++++++++++++++++++++++++------- src/cpp/ripple/Pathfinder.h | 22 +++++++---- 2 files changed, 74 insertions(+), 22 deletions(-) diff --git a/src/cpp/ripple/Pathfinder.cpp b/src/cpp/ripple/Pathfinder.cpp index d8739fb092..3a0bd05484 100644 --- a/src/cpp/ripple/Pathfinder.cpp +++ b/src/cpp/ripple/Pathfinder.cpp @@ -76,21 +76,57 @@ PathOption::PathOption(PathOption::pointer other) #endif // Return true, if path is a default path with an element. +// A path is a default path if it is implied via src, dst, send, and sendmax. // XXX Could be determined via STAmount bool Pathfinder::bDefaultPath(const STPath& spPath) { + if (2 == spPath.mPath.size()) { + // Empty path is a default. Don't need to add it to return set. + cLog(lsDEBUG) << "findPaths: empty path: direct"; + + return true; + } + + PathState::pointer pspCurrent = boost::make_shared(mDstAmount, mSrcAmount, mLedger); + + if (pspCurrent) + { + bool bDefault; + LedgerEntrySet lesActive(mLedger); + + pspCurrent->setExpanded(lesActive, spPath, mDstAccountID, mSrcAccountID); + + bDefault = pspCurrent->vpnNodes == mPsDefault->vpnNodes; + + // Path is a default (implied). Don't need to add it to return set. + cLog(lsDEBUG) << "findPaths: default path: indirect: " << spPath.getJson(0); + + return bDefault; + } + return false; - // return spPath.size() == 3 && spPath.mPath[1].mType; } // // XXX Optionally, specifying a source and destination issuer might be nice. Especially, to convert between issuers. However, this // functionality is left to the future. // -Pathfinder::Pathfinder(const RippleAddress& srcAccountID, const RippleAddress& dstAccountID, const uint160& srcCurrencyID, const uint160& srcIssuerID, const STAmount& dstAmount) - : mSrcAccountID(srcAccountID.getAccountID()), mDstAccountID(dstAccountID.getAccountID()), mDstAmount(dstAmount), mSrcCurrencyID(srcCurrencyID), mSrcIssuerID(srcIssuerID), mOrderBook(theApp->getLedgerMaster().getCurrentLedger()) +Pathfinder::Pathfinder(const RippleAddress& uSrcAccountID, const RippleAddress& uDstAccountID, const uint160& uSrcCurrencyID, const uint160& uSrcIssuerID, const STAmount& saDstAmount) + : mSrcAccountID(uSrcAccountID.getAccountID()), mDstAccountID(uDstAccountID.getAccountID()), mDstAmount(saDstAmount), mSrcCurrencyID(uSrcCurrencyID), mSrcIssuerID(uSrcIssuerID), mOrderBook(theApp->getLedgerMaster().getCurrentLedger()) { - mLedger=theApp->getLedgerMaster().getCurrentLedger(); + mLedger = theApp->getLedgerMaster().getCurrentLedger(); + mSrcAmount = STAmount(uSrcCurrencyID, uSrcIssuerID, 1, 0, true); // -1/uSrcIssuerID/uSrcIssuerID + + // Construct the default path for later comparison. + + mPsDefault = boost::make_shared(mDstAmount, mSrcAmount, mLedger); + + if (mPsDefault) + { + LedgerEntrySet lesActive(mLedger); + + mPsDefault->setExpanded(lesActive, STPath(), mDstAccountID, mSrcAccountID); + } } // If possible, returns a single path. @@ -114,7 +150,14 @@ bool Pathfinder::findPaths(int maxSearchSteps, int maxPay, STPathSet& retPathSet % RippleAddress::createHumanAccountID(mSrcIssuerID) ); - if (mLedger) { + if (!mPsDefault) + { + cLog(lsDEBUG) << boost::str(boost::format("findPaths: failed to generate default path.")); + + return false; + } + else if (mLedger) + { std::queue pqueue; STPathElement ele(mSrcAccountID, mSrcCurrencyID, @@ -160,16 +203,8 @@ bool Pathfinder::findPaths(int maxSearchSteps, int maxPay, STPathSet& retPathSet if (ele.mAccountID == mDstAccountID // Tail is destination account. && ele.mCurrencyID == mDstAmount.getCurrency()) { // With correct output currency. // Found a path to the destination. - - if (2 == path.mPath.size()) { - // Empty path is a default. Don't need to add it to return set. - cLog(lsDEBUG) << "findPaths: empty path: direct"; - - return true; - } - else if (bDefaultPath(path)) { - // Path is a default (implied). Don't need to add it to return set. - cLog(lsDEBUG) << "findPaths: default path: indirect: " << path.getJson(0); + if (bDefaultPath(path)) { + cLog(lsDEBUG) << "findPaths: default path: dropping: " << path.getJson(0); return true; } @@ -246,6 +281,15 @@ bool Pathfinder::findPaths(int maxSearchSteps, int maxPay, STPathSet& retPathSet bContinued = true; } + else + { + cLog(lsDEBUG) << + boost::str(boost::format("findPaths: SEEN: %s/%s --> %s/%s") + % RippleAddress::createHumanAccountID(ele.mAccountID) + % STAmount::createHumanCurrency(ele.mCurrencyID) + % RippleAddress::createHumanAccountID(line->getAccountIDPeer().getAccountID()) + % STAmount::createHumanCurrency(ele.mCurrencyID)); + } } // Every book that wants the source currency. diff --git a/src/cpp/ripple/Pathfinder.h b/src/cpp/ripple/Pathfinder.h index f72f334783..f890abbaf5 100644 --- a/src/cpp/ripple/Pathfinder.h +++ b/src/cpp/ripple/Pathfinder.h @@ -1,6 +1,10 @@ +#ifndef __PATHFINDER__ +#define __PATHFINDER__ + #include "SerializedTypes.h" #include "RippleAddress.h" #include "OrderBookDB.h" +#include "RippleCalc.h" #include #if 0 @@ -30,14 +34,16 @@ public: class Pathfinder { - uint160 mSrcAccountID; - uint160 mDstAccountID; - STAmount mDstAmount; - uint160 mSrcCurrencyID; - uint160 mSrcIssuerID; + uint160 mSrcAccountID; + uint160 mDstAccountID; + STAmount mDstAmount; + uint160 mSrcCurrencyID; + uint160 mSrcIssuerID; + STAmount mSrcAmount; - OrderBookDB mOrderBook; - Ledger::pointer mLedger; + OrderBookDB mOrderBook; + Ledger::pointer mLedger; + PathState::pointer mPsDefault; // std::list mBuildingPaths; // std::list mCompletePaths; @@ -56,4 +62,6 @@ public: bool bDefaultPath(const STPath& spPath); }; +#endif + // vim:ts=4