If an account sets noRipple on a RippleState, it can only be used as the first link in the path.

This commit is contained in:
JoelKatz
2013-09-22 20:48:40 -07:00
parent 0d744cc253
commit dc61fadc56
3 changed files with 25 additions and 7 deletions

View File

@@ -117,7 +117,7 @@ TER PathState::pushImply (
const uint160& uIssuerID) // --> Delivering this issuer.
{
const Node& pnPrv = vpnNodes.back ();
TER terResult = tesSUCCESS;
TER terResult = tesSUCCESS;
WriteLog (lsTRACE, RippleCalc) << "pushImply> "
<< RippleAddress::createHumanAccountID (uAccountID)
@@ -168,9 +168,9 @@ TER PathState::pushNode (
const uint160& uCurrencyID,
const uint160& uIssuerID)
{
Node pnCur;
Node pnCur;
const bool bFirst = vpnNodes.empty ();
const Node& pnPrv = bFirst ? Node () : vpnNodes.back ();
const Node& pnPrv = bFirst ? Node () : vpnNodes.back ();
// true, iff node is a ripple account. false, iff node is an offer node.
const bool bAccount = isSetBit (iType, STPathElement::typeAccount);
// true, iff currency supplied.
@@ -255,8 +255,8 @@ TER PathState::pushNode (
if (tesSUCCESS == terResult && !vpnNodes.empty ())
{
const Node& pnBck = vpnNodes.back ();
bool bBckAccount = isSetBit (pnBck.uFlags, STPathElement::typeAccount);
const Node& pnBck = vpnNodes.back ();
bool bBckAccount = isSetBit (pnBck.uFlags, STPathElement::typeAccount);
if (bBckAccount)
{
@@ -303,6 +303,13 @@ TER PathState::pushNode (
terResult = terNO_AUTH;
}
else if (isSetBit (sleRippleState->getFieldU32 (sfFlags), bHigh ? lsfHighNoRipple : lsfLowNoRipple) &&
(vpnNodes.size() > 1))
{ // If the link leaves the side that set no ripple, it must be the first link
WriteLog (lsWARNING, RippleCalc) << "pushNode: illegal use of noRipple link";
terResult = terNO_AUTH;
}
if (tesSUCCESS == terResult)
{

View File

@@ -454,6 +454,8 @@ int Pathfinder::getPathsOut (const uint160& currencyID, const uint160& accountID
nothing ();
else if (isDstCurrency && (dstAccount == rspEntry->getAccountIDPeer ()))
count += 10000; // count a path to the destination extra
else if (rspEntry->getNoRipple())
nothing (); // This isn't a useful path out
else
++count;
}
@@ -511,7 +513,10 @@ STPathSet& Pathfinder::getPaths(PathType_t const& type, bool addComplete)
break;
case nt_ACCOUNTS:
addLink(pathsIn, pathsOut, afADD_ACCOUNTS);
if (type.size() == 2) // "sa", so can use noRipple paths
addLink(pathsIn, pathsOut, afADD_ACCOUNTS | afALL_ACCOUNTS);
else
addLink(pathsIn, pathsOut, afADD_ACCOUNTS);
break;
case nt_BOOKS:
@@ -566,6 +571,7 @@ void Pathfinder::addLink(
}
else
{ // search for accounts to add
bool bAllAccounts = (addFlags & afALL_ACCOUNTS) != 0;
SLE::pointer sleEnd = mLedger->getSLEi(Ledger::getAccountRootIndex(uEndAccount));
if (sleEnd)
{
@@ -607,6 +613,10 @@ void Pathfinder::addLink(
candidates.push_back(std::make_pair(100000, acctID));
}
}
else if (!bAllAccounts && rspEntry.getNoRipple())
{
// Can't leave on this path
}
else if (acctID == mSrcAccountID)
{
// going back to the source is bad

View File

@@ -63,7 +63,7 @@ private:
enum NodeType
{
nt_SOURCE, // The source account with an issuer account, if required
nt_SOURCE, // The source account with an issuer account, if required
nt_ACCOUNTS, // Accounts that connect from this source/currency
nt_BOOKS, // Order books that connect to this currency
nt_XRP_BOOK, // The order book from this currency to XRP
@@ -118,6 +118,7 @@ private:
static const uint32 afOB_XRP = 0x010; // Add order book to XRP only
static const uint32 afOB_LAST = 0x040; // Must link to destination currency
static const uint32 afAC_LAST = 0x080; // Destination account only
static const uint32 afALL_ACCOUNTS = 0x100; // Include no ripple paths
};
boost::unordered_set<uint160> usAccountDestCurrencies (const RippleAddress& raAccountID, Ledger::ref lrLedger,