mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Refactor LedgerEntrySet:
* Split adjustOwnerCount to increment and decrement paths. * Move pathfinding-specific functions out of LedgerEntrySet * Convert members to free functions
This commit is contained in:
@@ -82,7 +82,7 @@ Taker::flow (Amounts amount, Offer const& offer, Account const& taker)
|
||||
taker, amount.in, fhZERO_IF_FROZEN));
|
||||
|
||||
// Get fee rate paid by taker
|
||||
std::uint32_t const taker_charge_rate (view ().rippleTransferRate (
|
||||
std::uint32_t const taker_charge_rate (rippleTransferRate (view (),
|
||||
taker, offer.account (), amount.in.getIssuer()));
|
||||
|
||||
// Skip some math when there's no fee
|
||||
@@ -106,7 +106,7 @@ Taker::flow (Amounts amount, Offer const& offer, Account const& taker)
|
||||
offer.account (), owner_amount.out, fhZERO_IF_FROZEN));
|
||||
|
||||
// Get fee rate paid by owner
|
||||
std::uint32_t const owner_charge_rate (view ().rippleTransferRate (
|
||||
std::uint32_t const owner_charge_rate (rippleTransferRate (view (),
|
||||
offer.account (), taker, amount.out.getIssuer()));
|
||||
|
||||
if (owner_charge_rate == QUALITY_ONE)
|
||||
|
||||
@@ -258,15 +258,6 @@ void LedgerEntrySet::entryDelete (SLE::ref sle)
|
||||
}
|
||||
}
|
||||
|
||||
bool LedgerEntrySet::hasChanges ()
|
||||
{
|
||||
for (auto const& it : mEntries)
|
||||
if (it.second.mAction != taaCACHED)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Json::Value LedgerEntrySet::getJson (int) const
|
||||
{
|
||||
Json::Value ret (Json::objectValue);
|
||||
@@ -383,20 +374,22 @@ SLE::pointer LedgerEntrySet::getForMod (uint256 const& node, Ledger::ref ledger,
|
||||
newMods.insert (std::make_pair (node, ret));
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
bool LedgerEntrySet::threadTx (RippleAddress const& threadTo, Ledger::ref ledger,
|
||||
NodeToLedgerEntry& newMods)
|
||||
{
|
||||
SLE::pointer sle = getForMod (
|
||||
Ledger::getAccountRootIndex (threadTo.getAccountID ()), ledger, newMods);
|
||||
|
||||
#ifdef META_DEBUG
|
||||
WriteLog (lsTRACE, LedgerEntrySet) << "Thread to " << threadTo.getAccountID ();
|
||||
#endif
|
||||
SLE::pointer sle = getForMod (Ledger::getAccountRootIndex (threadTo.getAccountID ()), ledger, newMods);
|
||||
|
||||
if (!sle)
|
||||
{
|
||||
WriteLog (lsFATAL, LedgerEntrySet) << "Threading to non-existent account: " << threadTo.humanAccountID ();
|
||||
WriteLog (lsFATAL, LedgerEntrySet) <<
|
||||
"Threading to non-existent account: " << threadTo.humanAccountID ();
|
||||
assert (false);
|
||||
return false;
|
||||
}
|
||||
@@ -1028,29 +1021,52 @@ uint256 LedgerEntrySet::getNextLedgerIndex (
|
||||
return next;
|
||||
}
|
||||
|
||||
// If there is a count, adjust the owner count by iAmount. Otherwise, compute
|
||||
// the owner count and store it.
|
||||
void LedgerEntrySet::ownerCountAdjust (
|
||||
Account const& owner, int iAmount, SLE::ref sleAccountRoot)
|
||||
void LedgerEntrySet::incrementOwnerCount (SLE::ref sleAccount)
|
||||
{
|
||||
auto sleHold = sleAccountRoot ? SLE::pointer ()
|
||||
: entryCache (ltACCOUNT_ROOT, Ledger::getAccountRootIndex (owner));
|
||||
assert (sleAccount);
|
||||
|
||||
SLE::ref sleRoot = sleAccountRoot
|
||||
? sleAccountRoot
|
||||
: sleHold;
|
||||
std::uint32_t const current_count = sleAccount->getFieldU32 (sfOwnerCount);
|
||||
|
||||
const std::uint32_t uOwnerCount = sleRoot->getFieldU32 (sfOwnerCount);
|
||||
|
||||
const std::uint32_t uNew = iAmount + int (uOwnerCount) > 0
|
||||
? uOwnerCount + iAmount
|
||||
: 0;
|
||||
|
||||
if (uOwnerCount != uNew)
|
||||
if (current_count == std::numeric_limits<std::uint32_t>::max ())
|
||||
{
|
||||
sleRoot->setFieldU32 (sfOwnerCount, uOwnerCount + iAmount);
|
||||
entryModify (sleRoot);
|
||||
WriteLog (lsFATAL, LedgerEntrySet) <<
|
||||
"Account " << sleAccount->getFieldAccount160 (sfAccount) <<
|
||||
" owner count exceeds max!";
|
||||
return;
|
||||
}
|
||||
|
||||
sleAccount->setFieldU32 (sfOwnerCount, current_count + 1);
|
||||
entryModify (sleAccount);
|
||||
}
|
||||
|
||||
void LedgerEntrySet::incrementOwnerCount (Account const& owner)
|
||||
{
|
||||
incrementOwnerCount(entryCache (ltACCOUNT_ROOT,
|
||||
Ledger::getAccountRootIndex (owner)));
|
||||
}
|
||||
|
||||
void LedgerEntrySet::decrementOwnerCount (SLE::ref sleAccount)
|
||||
{
|
||||
assert (sleAccount);
|
||||
|
||||
std::uint32_t const current_count = sleAccount->getFieldU32 (sfOwnerCount);
|
||||
|
||||
if (current_count == 0)
|
||||
{
|
||||
WriteLog (lsFATAL, LedgerEntrySet) <<
|
||||
"Account " << sleAccount->getFieldAccount160 (sfAccount) <<
|
||||
" owner count is already 0!";
|
||||
return;
|
||||
}
|
||||
|
||||
sleAccount->setFieldU32 (sfOwnerCount, current_count - 1);
|
||||
entryModify (sleAccount);
|
||||
}
|
||||
|
||||
void LedgerEntrySet::decrementOwnerCount (Account const& owner)
|
||||
{
|
||||
decrementOwnerCount(entryCache (ltACCOUNT_ROOT,
|
||||
Ledger::getAccountRootIndex (owner)));
|
||||
}
|
||||
|
||||
TER LedgerEntrySet::offerDelete (SLE::pointer sleOffer)
|
||||
@@ -1074,149 +1090,13 @@ TER LedgerEntrySet::offerDelete (SLE::pointer sleOffer)
|
||||
false, uBookNode, uDirectory, offerIndex, true, false);
|
||||
|
||||
if (tesSUCCESS == terResult)
|
||||
ownerCountAdjust (owner, -1);
|
||||
decrementOwnerCount (owner);
|
||||
|
||||
entryDelete (sleOffer);
|
||||
|
||||
return (terResult == tesSUCCESS) ? terResult2 : terResult;
|
||||
}
|
||||
|
||||
// Returns amount owed by uToAccountID to uFromAccountID.
|
||||
// <-- $owed/currency/uToAccountID:
|
||||
// positive: uFromAccountID holds IOUs.,
|
||||
// negative: uFromAccountID owes IOUs.
|
||||
STAmount LedgerEntrySet::rippleOwed (
|
||||
Account const& uToAccountID, Account const& uFromAccountID,
|
||||
Currency const& currency)
|
||||
{
|
||||
STAmount saBalance;
|
||||
SLE::pointer sleRippleState = entryCache (
|
||||
ltRIPPLE_STATE,
|
||||
Ledger::getRippleStateIndex (
|
||||
uToAccountID, uFromAccountID, currency));
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
saBalance = sleRippleState->getFieldAmount (sfBalance);
|
||||
|
||||
if (uToAccountID < uFromAccountID)
|
||||
saBalance.negate ();
|
||||
|
||||
saBalance.setIssuer (uToAccountID);
|
||||
}
|
||||
else
|
||||
{
|
||||
saBalance.clear ({currency, uToAccountID});
|
||||
|
||||
WriteLog (lsDEBUG, LedgerEntrySet) << "rippleOwed:" <<
|
||||
" No credit line between " <<
|
||||
to_string (uFromAccountID) <<
|
||||
" and " << to_string (uToAccountID) <<
|
||||
" for " << to_string (currency);
|
||||
}
|
||||
|
||||
return saBalance;
|
||||
}
|
||||
|
||||
// Maximum amount of IOUs uToAccountID will hold from uFromAccountID.
|
||||
// <-- $amount/currency/uToAccountID.
|
||||
STAmount LedgerEntrySet::rippleLimit (
|
||||
Account const& uToAccountID, Account const& uFromAccountID,
|
||||
Currency const& currency)
|
||||
{
|
||||
STAmount saLimit;
|
||||
auto sleRippleState = entryCache (
|
||||
ltRIPPLE_STATE,
|
||||
Ledger::getRippleStateIndex (
|
||||
uToAccountID, uFromAccountID, currency));
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
saLimit = sleRippleState->getFieldAmount (
|
||||
uToAccountID < uFromAccountID ? sfLowLimit : sfHighLimit);
|
||||
saLimit.setIssuer (uToAccountID);
|
||||
}
|
||||
else
|
||||
{
|
||||
saLimit.clear ({currency, uToAccountID});
|
||||
}
|
||||
|
||||
return saLimit;
|
||||
|
||||
}
|
||||
|
||||
std::uint32_t LedgerEntrySet::rippleTransferRate (Account const& issuer)
|
||||
{
|
||||
SLE::pointer sleAccount (entryCache (
|
||||
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (issuer)));
|
||||
|
||||
std::uint32_t uQuality =
|
||||
sleAccount && sleAccount->isFieldPresent (sfTransferRate)
|
||||
? sleAccount->getFieldU32 (sfTransferRate)
|
||||
: QUALITY_ONE;
|
||||
|
||||
WriteLog (lsTRACE, LedgerEntrySet) << "rippleTransferRate:" <<
|
||||
" issuer=" << to_string (issuer) <<
|
||||
" account_exists=" << std::boolalpha << bool(sleAccount) <<
|
||||
" transfer_rate=" << (uQuality / 1000000000.0);
|
||||
|
||||
return uQuality;
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
LedgerEntrySet::rippleTransferRate (Account const& uSenderID,
|
||||
Account const& uReceiverID,
|
||||
Account const& issuer)
|
||||
{
|
||||
// If calculating the transfer rate from or to the issuer of the currency
|
||||
// no fees are assessed.
|
||||
return uSenderID == issuer || uReceiverID == issuer
|
||||
? QUALITY_ONE
|
||||
: rippleTransferRate (issuer);
|
||||
}
|
||||
|
||||
// XXX Might not need this, might store in nodes on calc reverse.
|
||||
std::uint32_t
|
||||
LedgerEntrySet::rippleQualityIn (
|
||||
Account const& uToAccountID, Account const& uFromAccountID,
|
||||
Currency const& uCurrencyID, SField::ref sfLow, SField::ref sfHigh)
|
||||
{
|
||||
std::uint32_t uQuality (QUALITY_ONE);
|
||||
|
||||
if (uToAccountID == uFromAccountID)
|
||||
return uQuality;
|
||||
|
||||
SLE::pointer sleRippleState (entryCache (ltRIPPLE_STATE,
|
||||
Ledger::getRippleStateIndex (uToAccountID, uFromAccountID, uCurrencyID)));
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
SField::ref sfField = uToAccountID < uFromAccountID ? sfLow : sfHigh;
|
||||
|
||||
uQuality = sleRippleState->isFieldPresent (sfField)
|
||||
? sleRippleState->getFieldU32 (sfField)
|
||||
: QUALITY_ONE;
|
||||
|
||||
if (!uQuality)
|
||||
uQuality = 1; // Avoid divide by zero.
|
||||
}
|
||||
else
|
||||
{
|
||||
// XXX Ideally, catch no before this. So we can assert to be stricter.
|
||||
uQuality = QUALITY_ONE;
|
||||
}
|
||||
|
||||
WriteLog (lsTRACE, LedgerEntrySet) << "rippleQuality: " <<
|
||||
(sfLow == sfLowQualityIn ? "in" : "out") <<
|
||||
" uToAccountID=" << to_string (uToAccountID) <<
|
||||
" uFromAccountID=" << to_string (uFromAccountID) <<
|
||||
" uCurrencyID=" << to_string (uCurrencyID) <<
|
||||
" bLine=" << std::boolalpha << bool(sleRippleState) <<
|
||||
" uQuality=" << (uQuality / 1000000000.0);
|
||||
|
||||
return uQuality;
|
||||
}
|
||||
|
||||
// Return how much of issuer's currency IOUs that account holds. May be
|
||||
// negative.
|
||||
// <-- IOU's account has of issuer.
|
||||
@@ -1292,7 +1172,7 @@ STAmount LedgerEntrySet::accountHolds (
|
||||
}
|
||||
else
|
||||
{
|
||||
saAmount = rippleHolds (account, currency, issuer, zeroIfFrozen);
|
||||
saAmount = rippleHolds (account, currency, issuer, zeroIfFrozen);
|
||||
|
||||
WriteLog (lsTRACE, LedgerEntrySet) << "accountHolds:" <<
|
||||
" account=" << to_string (account) <<
|
||||
@@ -1388,7 +1268,7 @@ STAmount LedgerEntrySet::rippleTransferFee (
|
||||
{
|
||||
if (uSenderID != issuer && uReceiverID != issuer)
|
||||
{
|
||||
std::uint32_t uTransitRate = rippleTransferRate (issuer);
|
||||
std::uint32_t uTransitRate = rippleTransferRate (*this, issuer);
|
||||
|
||||
if (QUALITY_ONE != uTransitRate)
|
||||
{
|
||||
@@ -1477,28 +1357,26 @@ TER LedgerEntrySet::trustCreate (
|
||||
sleRippleState->setFieldU32 (
|
||||
bSetHigh ? sfHighQualityOut : sfLowQualityOut, uQualityOut);
|
||||
|
||||
std::uint32_t uFlags = bSetHigh ? lsfHighReserve : lsfLowReserve;
|
||||
std::uint32_t uFlags = bSetHigh ? lsfHighReserve : lsfLowReserve;
|
||||
|
||||
if (bAuth)
|
||||
{
|
||||
uFlags |= (bSetHigh ? lsfHighAuth : lsfLowAuth);
|
||||
uFlags |= (bSetHigh ? lsfHighAuth : lsfLowAuth);
|
||||
}
|
||||
if (bNoRipple)
|
||||
{
|
||||
uFlags |= (bSetHigh ? lsfHighNoRipple : lsfLowNoRipple);
|
||||
uFlags |= (bSetHigh ? lsfHighNoRipple : lsfLowNoRipple);
|
||||
}
|
||||
if (bFreeze)
|
||||
{
|
||||
uFlags |= (!bSetHigh ? lsfLowFreeze : lsfHighFreeze);
|
||||
uFlags |= (!bSetHigh ? lsfLowFreeze : lsfHighFreeze);
|
||||
}
|
||||
|
||||
sleRippleState->setFieldU32 (sfFlags, uFlags);
|
||||
ownerCountAdjust (
|
||||
bSetDst ? uDstAccountID : uSrcAccountID, 1, sleAccount);
|
||||
incrementOwnerCount (sleAccount);
|
||||
|
||||
// ONLY: Create ripple balance.
|
||||
sleRippleState->setFieldAmount (
|
||||
sfBalance, bSetHigh ? -saBalance : saBalance);
|
||||
sleRippleState->setFieldAmount (sfBalance, bSetHigh ? -saBalance : saBalance);
|
||||
}
|
||||
|
||||
return terResult;
|
||||
@@ -1637,10 +1515,7 @@ TER LedgerEntrySet::rippleCredit (
|
||||
// Sender quality out is 0.
|
||||
{
|
||||
// Clear the reserve of the sender, possibly delete the line!
|
||||
auto sleSender = entryCache (
|
||||
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uSenderID));
|
||||
|
||||
ownerCountAdjust (uSenderID, -1, sleSender);
|
||||
decrementOwnerCount (uSenderID);
|
||||
|
||||
// Clear reserve flag.
|
||||
sleRippleState->setFieldU32 (
|
||||
@@ -1824,4 +1699,29 @@ TER LedgerEntrySet::accountSend (
|
||||
return terResult;
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
rippleTransferRate (LedgerEntrySet& ledger, Account const& issuer)
|
||||
{
|
||||
SLE::pointer sleAccount (ledger.entryCache (
|
||||
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (issuer)));
|
||||
|
||||
std::uint32_t quality = QUALITY_ONE;
|
||||
|
||||
if (sleAccount && sleAccount->isFieldPresent (sfTransferRate))
|
||||
quality = sleAccount->getFieldU32 (sfTransferRate);
|
||||
|
||||
return quality;
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
rippleTransferRate (LedgerEntrySet& ledger, Account const& uSenderID,
|
||||
Account const& uReceiverID, Account const& issuer)
|
||||
{
|
||||
// If calculating the transfer rate from or to the issuer of the currency
|
||||
// no fees are assessed.
|
||||
return (uSenderID == issuer || uReceiverID == issuer)
|
||||
? QUALITY_ONE
|
||||
: rippleTransferRate (ledger, issuer);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -163,7 +163,6 @@ public:
|
||||
void entryCreate (SLE::ref); // This entry will be created
|
||||
void entryDelete (SLE::ref); // This entry will be deleted
|
||||
void entryModify (SLE::ref); // This entry will be modified
|
||||
bool hasChanges (); // True if LES has any changes
|
||||
|
||||
// higher-level ledger functions
|
||||
SLE::pointer entryCreate (LedgerEntryType letType, uint256 const& uIndex);
|
||||
@@ -194,8 +193,15 @@ public:
|
||||
uint256 getNextLedgerIndex (uint256 const& uHash);
|
||||
uint256 getNextLedgerIndex (uint256 const& uHash, uint256 const& uEnd);
|
||||
|
||||
void ownerCountAdjust (Account const& uOwnerID, int iAmount,
|
||||
SLE::ref sleAccountRoot = SLE::pointer ());
|
||||
/** @{ */
|
||||
void incrementOwnerCount (SLE::ref sleAccount);
|
||||
void incrementOwnerCount (Account const& owner);
|
||||
/** @} */
|
||||
|
||||
/** @{ */
|
||||
void decrementOwnerCount (SLE::ref sleAccount);
|
||||
void decrementOwnerCount (Account const& owner);
|
||||
/** @} */
|
||||
|
||||
// Offer functions.
|
||||
TER offerDelete (SLE::pointer);
|
||||
@@ -205,33 +211,6 @@ public:
|
||||
}
|
||||
|
||||
// Balance functions.
|
||||
std::uint32_t rippleTransferRate (Account const& issuer);
|
||||
std::uint32_t rippleTransferRate (
|
||||
Account const& uSenderID, Account const& uReceiverID,
|
||||
Account const& issuer);
|
||||
|
||||
STAmount rippleOwed (
|
||||
Account const& uToAccountID, Account const& uFromAccountID,
|
||||
Currency const& currency);
|
||||
STAmount rippleLimit (
|
||||
Account const& uToAccountID, Account const& uFromAccountID,
|
||||
Currency const& currency);
|
||||
|
||||
std::uint32_t rippleQualityIn (
|
||||
Account const& uToAccountID, Account const& uFromAccountID,
|
||||
Currency const& currency,
|
||||
SField::ref sfLow = sfLowQualityIn,
|
||||
SField::ref sfHigh = sfHighQualityIn);
|
||||
|
||||
std::uint32_t rippleQualityOut (
|
||||
Account const& uToAccountID, Account const& uFromAccountID,
|
||||
Currency const& currency)
|
||||
{
|
||||
return rippleQualityIn (
|
||||
uToAccountID, uFromAccountID, currency,
|
||||
sfLowQualityOut, sfHighQualityOut);
|
||||
}
|
||||
|
||||
bool isFrozen (
|
||||
Account const& account,
|
||||
Currency const& currency,
|
||||
@@ -347,6 +326,14 @@ private:
|
||||
Account const& issuer, FreezeHandling zeroIfFrozen);
|
||||
};
|
||||
|
||||
// NIKB FIXME: move these to the right place
|
||||
std::uint32_t
|
||||
rippleTransferRate (LedgerEntrySet& ledger, Account const& issuer);
|
||||
|
||||
std::uint32_t
|
||||
rippleTransferRate (LedgerEntrySet& ledger, Account const& uSenderID,
|
||||
Account const& uReceiverID, Account const& issuer);
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3103,7 +3103,7 @@ void NetworkOPsImp::getBookPage (
|
||||
if (iLeft == 0 || iLeft > 300)
|
||||
iLeft = 300;
|
||||
|
||||
auto uTransferRate = lesActive.rippleTransferRate (book.out.account);
|
||||
auto uTransferRate = rippleTransferRate (lesActive, book.out.account);
|
||||
|
||||
while (! bDone && iLeft-- > 0)
|
||||
{
|
||||
@@ -3299,7 +3299,7 @@ void NetworkOPsImp::getBookPage (
|
||||
if (iLeft == 0 || iLeft > 300)
|
||||
iLeft = 300;
|
||||
|
||||
auto uTransferRate = lesActive.rippleTransferRate (book.out.account);
|
||||
auto uTransferRate = rippleTransferRate (lesActive, book.out.account);
|
||||
|
||||
const bool bGlobalFreeze = lesActive.isGlobalFrozen (book.out.account) ||
|
||||
lesActive.isGlobalFrozen (book.in.account);
|
||||
|
||||
@@ -314,13 +314,13 @@ TER PathState::pushNode (
|
||||
|
||||
if (resultCode == tesSUCCESS)
|
||||
{
|
||||
STAmount saOwed = lesEntries.rippleOwed (
|
||||
STAmount saOwed = credit_balance (lesEntries,
|
||||
node.account_, backNode.account_,
|
||||
node.issue_.currency);
|
||||
STAmount saLimit;
|
||||
|
||||
if (saOwed <= zero) {
|
||||
saLimit = lesEntries.rippleLimit (
|
||||
saLimit = credit_limit (lesEntries,
|
||||
node.account_,
|
||||
backNode.account_,
|
||||
node.issue_.currency);
|
||||
|
||||
@@ -1071,4 +1071,51 @@ void Pathfinder::initPathTable()
|
||||
});
|
||||
}
|
||||
|
||||
STAmount
|
||||
credit_limit (
|
||||
LedgerEntrySet& ledger, Account const& account,
|
||||
Account const& issuer, Currency const& currency)
|
||||
{
|
||||
STAmount saLimit ({currency, account});
|
||||
|
||||
auto sleRippleState = ledger.entryCache (ltRIPPLE_STATE,
|
||||
Ledger::getRippleStateIndex (account, issuer, currency));
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
saLimit = sleRippleState->getFieldAmount (
|
||||
account < issuer ? sfLowLimit : sfHighLimit);
|
||||
saLimit.setIssuer (account);
|
||||
}
|
||||
|
||||
assert (saLimit.getIssuer () == account);
|
||||
assert (saLimit.getCurrency () == currency);
|
||||
return saLimit;
|
||||
}
|
||||
|
||||
STAmount
|
||||
credit_balance (
|
||||
LedgerEntrySet& ledger, Account const& account,
|
||||
Account const& issuer, Currency const& currency)
|
||||
{
|
||||
STAmount saBalance ({currency, account});
|
||||
|
||||
auto sleRippleState = ledger.entryCache (ltRIPPLE_STATE,
|
||||
Ledger::getRippleStateIndex (account, issuer, currency));
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
saBalance = sleRippleState->getFieldAmount (sfBalance);
|
||||
|
||||
if (account < issuer)
|
||||
saBalance.negate ();
|
||||
|
||||
saBalance.setIssuer (account);
|
||||
}
|
||||
|
||||
assert (saBalance.getIssuer () == account);
|
||||
assert (saBalance.getCurrency () == currency);
|
||||
return saBalance;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -165,6 +165,29 @@ CurrencySet usAccountSourceCurrencies
|
||||
RippleLineCache::ref lrLedger,
|
||||
bool includeXRP);
|
||||
|
||||
/** Calculate the maximum amount of IOUs that an account can hold
|
||||
@param ledger the ledger to check against.
|
||||
@param account the account of interest.
|
||||
@param issuer the issuer of the IOU.
|
||||
@param currency the IOU to check.
|
||||
@return The maximum amount that can be held.
|
||||
*/
|
||||
STAmount
|
||||
credit_limit (
|
||||
LedgerEntrySet& ledger, Account const& account,
|
||||
Account const& issuer, Currency const& currency);
|
||||
|
||||
/** Returns the amount of IOUs issued by issuer that are held by an account
|
||||
@param ledger the ledger to check against.
|
||||
@param account the account of interest.
|
||||
@param issuer the issuer of the IOU.
|
||||
@param currency the IOU to check.
|
||||
*/
|
||||
STAmount
|
||||
credit_balance (
|
||||
LedgerEntrySet& ledger, Account const& account,
|
||||
Account const& issuer, Currency const& currency);
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -52,13 +52,13 @@ TER PathCursor::forwardLiquidityForAccount () const
|
||||
nextNode().isAccount() ? nextNode().account_ : node().account_;
|
||||
|
||||
std::uint32_t uQualityIn = nodeIndex_
|
||||
? ledger().rippleQualityIn (
|
||||
? quality_in (ledger(),
|
||||
node().account_,
|
||||
previousAccountID,
|
||||
node().issue_.currency)
|
||||
: QUALITY_ONE;
|
||||
std::uint32_t uQualityOut = (nodeIndex_ == lastNodeIndex)
|
||||
? ledger().rippleQualityOut (
|
||||
? quality_out (ledger(),
|
||||
node().account_,
|
||||
nextAccountID,
|
||||
node().issue_.currency)
|
||||
@@ -230,7 +230,7 @@ TER PathCursor::forwardLiquidityForAccount () const
|
||||
rippleLiquidity (
|
||||
rippleCalc_,
|
||||
QUALITY_ONE,
|
||||
ledger().rippleTransferRate (node().account_),
|
||||
rippleTransferRate (ledger(), node().account_),
|
||||
previousNode().saFwdRedeem,
|
||||
node().saRevIssue,
|
||||
saPrvRedeemAct,
|
||||
@@ -299,7 +299,7 @@ TER PathCursor::forwardLiquidityForAccount () const
|
||||
rippleLiquidity (
|
||||
rippleCalc_,
|
||||
QUALITY_ONE,
|
||||
ledger().rippleTransferRate (node().account_),
|
||||
rippleTransferRate (ledger(), node().account_),
|
||||
previousNode().saFwdRedeem,
|
||||
node().saRevDeliver,
|
||||
saPrvRedeemAct,
|
||||
@@ -445,7 +445,7 @@ TER PathCursor::forwardLiquidityForAccount () const
|
||||
rippleLiquidity (
|
||||
rippleCalc_,
|
||||
QUALITY_ONE,
|
||||
ledger().rippleTransferRate (node().account_),
|
||||
rippleTransferRate (ledger(), node().account_),
|
||||
previousNode().saFwdDeliver,
|
||||
node().saRevIssue,
|
||||
saPrvDeliverAct,
|
||||
@@ -479,7 +479,7 @@ TER PathCursor::forwardLiquidityForAccount () const
|
||||
rippleLiquidity (
|
||||
rippleCalc_,
|
||||
QUALITY_ONE,
|
||||
ledger().rippleTransferRate (node().account_),
|
||||
rippleTransferRate (ledger(), node().account_),
|
||||
previousNode().saFwdDeliver,
|
||||
node().saRevDeliver,
|
||||
saPrvDeliverAct,
|
||||
|
||||
@@ -53,7 +53,7 @@ TER PathCursor::reverseLiquidity () const
|
||||
|
||||
// node.transferRate_ caches the output transfer rate for this node.
|
||||
node().transferRate_ = STAmount::saFromRate (
|
||||
ledger().rippleTransferRate (node().issue_.account));
|
||||
rippleTransferRate (ledger(), node().issue_.account));
|
||||
|
||||
if (node().isAccount ())
|
||||
return reverseLiquidityForAccount ();
|
||||
|
||||
@@ -61,7 +61,7 @@ TER PathCursor::reverseLiquidityForAccount () const
|
||||
// This is the quality from from the previous node to this one.
|
||||
const std::uint32_t uQualityIn
|
||||
= (nodeIndex_ != 0)
|
||||
? ledger().rippleQualityIn (
|
||||
? quality_in (ledger(),
|
||||
node().account_,
|
||||
previousAccountID,
|
||||
node().issue_.currency)
|
||||
@@ -70,7 +70,7 @@ TER PathCursor::reverseLiquidityForAccount () const
|
||||
// And this is the quality from the next one to this one.
|
||||
const std::uint32_t uQualityOut
|
||||
= (nodeIndex_ != lastNodeIndex)
|
||||
? ledger().rippleQualityOut (
|
||||
? quality_out (ledger(),
|
||||
node().account_,
|
||||
nextAccountID,
|
||||
node().issue_.currency)
|
||||
@@ -79,15 +79,15 @@ TER PathCursor::reverseLiquidityForAccount () const
|
||||
// For previousNodeIsAccount:
|
||||
// Previous account is already owed.
|
||||
const STAmount saPrvOwed = (previousNodeIsAccount && nodeIndex_ != 0)
|
||||
? ledger().rippleOwed (
|
||||
? credit_balance (ledger(),
|
||||
node().account_,
|
||||
previousAccountID,
|
||||
node().issue_.currency)
|
||||
: STAmount (node().issue_);
|
||||
: STAmount (node().issue_);
|
||||
|
||||
// The limit amount that the previous account may owe.
|
||||
const STAmount saPrvLimit = (previousNodeIsAccount && nodeIndex_ != 0)
|
||||
? ledger().rippleLimit (
|
||||
? credit_limit (ledger(),
|
||||
node().account_,
|
||||
previousAccountID,
|
||||
node().issue_.currency)
|
||||
@@ -95,7 +95,7 @@ TER PathCursor::reverseLiquidityForAccount () const
|
||||
|
||||
// Next account is owed.
|
||||
const STAmount saNxtOwed = (nextNodeIsAccount && nodeIndex_ != lastNodeIndex)
|
||||
? ledger().rippleOwed (
|
||||
? credit_balance (ledger(),
|
||||
node().account_,
|
||||
nextAccountID,
|
||||
node().issue_.currency)
|
||||
@@ -312,7 +312,7 @@ TER PathCursor::reverseLiquidityForAccount () const
|
||||
rippleLiquidity (
|
||||
rippleCalc_,
|
||||
QUALITY_ONE,
|
||||
ledger().rippleTransferRate (node().account_),
|
||||
rippleTransferRate (ledger(), node().account_),
|
||||
saPrvRedeemReq,
|
||||
node().saRevIssue,
|
||||
previousNode().saRevRedeem,
|
||||
@@ -398,7 +398,7 @@ TER PathCursor::reverseLiquidityForAccount () const
|
||||
rippleLiquidity (
|
||||
rippleCalc_,
|
||||
QUALITY_ONE,
|
||||
ledger().rippleTransferRate (node().account_),
|
||||
rippleTransferRate (ledger(), node().account_),
|
||||
saPrvRedeemReq,
|
||||
node().saRevDeliver,
|
||||
previousNode().saRevRedeem,
|
||||
@@ -547,7 +547,7 @@ TER PathCursor::reverseLiquidityForAccount () const
|
||||
rippleLiquidity (
|
||||
rippleCalc_,
|
||||
QUALITY_ONE,
|
||||
ledger().rippleTransferRate (node().account_),
|
||||
rippleTransferRate (ledger(), node().account_),
|
||||
saPrvDeliverReq,
|
||||
node().saRevIssue,
|
||||
previousNode().saRevDeliver,
|
||||
@@ -580,7 +580,7 @@ TER PathCursor::reverseLiquidityForAccount () const
|
||||
rippleLiquidity (
|
||||
rippleCalc_,
|
||||
QUALITY_ONE,
|
||||
ledger().rippleTransferRate (node().account_),
|
||||
rippleTransferRate (ledger(), node().account_),
|
||||
saPrvDeliverReq,
|
||||
node().saRevDeliver,
|
||||
previousNode().saRevDeliver,
|
||||
|
||||
@@ -197,5 +197,62 @@ void rippleLiquidity (
|
||||
<< " saCurAct=" << saCurAct;
|
||||
}
|
||||
|
||||
static
|
||||
std::uint32_t
|
||||
rippleQuality (
|
||||
LedgerEntrySet& ledger,
|
||||
Account const& destination,
|
||||
Account const& source,
|
||||
Currency const& currency,
|
||||
SField::ref sfLow,
|
||||
SField::ref sfHigh)
|
||||
{
|
||||
std::uint32_t uQuality (QUALITY_ONE);
|
||||
|
||||
if (destination != source)
|
||||
{
|
||||
SLE::pointer sleRippleState (ledger.entryCache (ltRIPPLE_STATE,
|
||||
Ledger::getRippleStateIndex (destination, source, currency)));
|
||||
|
||||
// we should be able to assert(sleRippleState) here
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
SField::ref sfField = destination < source ? sfLow : sfHigh;
|
||||
|
||||
uQuality = sleRippleState->isFieldPresent (sfField)
|
||||
? sleRippleState->getFieldU32 (sfField)
|
||||
: QUALITY_ONE;
|
||||
|
||||
if (!uQuality)
|
||||
uQuality = 1; // Avoid divide by zero.
|
||||
}
|
||||
}
|
||||
|
||||
return uQuality;
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
quality_in (
|
||||
LedgerEntrySet& ledger,
|
||||
Account const& uToAccountID,
|
||||
Account const& uFromAccountID,
|
||||
Currency const& currency)
|
||||
{
|
||||
return rippleQuality (ledger, uToAccountID, uFromAccountID, currency,
|
||||
sfLowQualityIn, sfHighQualityIn);
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
quality_out (
|
||||
LedgerEntrySet& ledger,
|
||||
Account const& uToAccountID,
|
||||
Account const& uFromAccountID,
|
||||
Currency const& currency)
|
||||
{
|
||||
return rippleQuality (ledger, uToAccountID, uFromAccountID, currency,
|
||||
sfLowQualityOut, sfHighQualityOut);
|
||||
}
|
||||
|
||||
} // path
|
||||
} // ripple
|
||||
|
||||
@@ -39,6 +39,20 @@ void rippleLiquidity (
|
||||
STAmount& saCurAct,
|
||||
std::uint64_t& uRateMax);
|
||||
|
||||
std::uint32_t
|
||||
quality_in (
|
||||
LedgerEntrySet& ledger,
|
||||
Account const& uToAccountID,
|
||||
Account const& uFromAccountID,
|
||||
Currency const& currency);
|
||||
|
||||
std::uint32_t
|
||||
quality_out (
|
||||
LedgerEntrySet& ledger,
|
||||
Account const& uToAccountID,
|
||||
Account const& uFromAccountID,
|
||||
Currency const& currency);
|
||||
|
||||
} // path
|
||||
} // ripple
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
TER const result = mEngine->view ().dirDelete (false, hint,
|
||||
Ledger::getOwnerDirIndex (ticket_owner), ticketId, false, (hint == 0));
|
||||
|
||||
mEngine->view ().ownerCountAdjust (ticket_owner, -1);
|
||||
mEngine->view ().decrementOwnerCount (mTxnAccount);
|
||||
mEngine->view ().entryDelete (sleTicket);
|
||||
|
||||
return result;
|
||||
|
||||
@@ -461,7 +461,6 @@ public:
|
||||
{
|
||||
// Ledger is final, insufficent reserve to create offer, processed
|
||||
// something.
|
||||
|
||||
// Consider the offer unfunded. Treat as tesSUCCESS.
|
||||
}
|
||||
}
|
||||
@@ -490,7 +489,7 @@ public:
|
||||
if (tesSUCCESS == terResult)
|
||||
{
|
||||
// Update owner count.
|
||||
view.ownerCountAdjust (mTxnAccountID, 1, sleCreator);
|
||||
view.incrementOwnerCount (sleCreator);
|
||||
|
||||
uint256 const uBookBase (Ledger::getBookBase (
|
||||
{{uPaysCurrency, uPaysIssuerID},
|
||||
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
sleTicket->setFieldU64(sfOwnerNode, hint);
|
||||
|
||||
// If we succeeded, the new entry counts agains the creator's reserve.
|
||||
mEngine->view ().ownerCountAdjust (mTxnAccountID, 1, mTxnAccount);
|
||||
mEngine->view ().incrementOwnerCount (mTxnAccount);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -309,8 +309,7 @@ public:
|
||||
if (bLowReserveSet && !bLowReserved)
|
||||
{
|
||||
// Set reserve for low account.
|
||||
|
||||
mEngine->view ().ownerCountAdjust (uLowAccountID, 1, sleLowAccount);
|
||||
mEngine->view ().incrementOwnerCount (sleLowAccount);
|
||||
uFlagsOut |= lsfLowReserve;
|
||||
|
||||
if (!bHigh)
|
||||
@@ -320,16 +319,14 @@ public:
|
||||
if (bLowReserveClear && bLowReserved)
|
||||
{
|
||||
// Clear reserve for low account.
|
||||
|
||||
mEngine->view ().ownerCountAdjust (uLowAccountID, -1, sleLowAccount);
|
||||
mEngine->view ().decrementOwnerCount (sleLowAccount);
|
||||
uFlagsOut &= ~lsfLowReserve;
|
||||
}
|
||||
|
||||
if (bHighReserveSet && !bHighReserved)
|
||||
{
|
||||
// Set reserve for high account.
|
||||
|
||||
mEngine->view ().ownerCountAdjust (uHighAccountID, 1, sleHighAccount);
|
||||
mEngine->view ().incrementOwnerCount (sleHighAccount);
|
||||
uFlagsOut |= lsfHighReserve;
|
||||
|
||||
if (bHigh)
|
||||
@@ -339,8 +336,7 @@ public:
|
||||
if (bHighReserveClear && bHighReserved)
|
||||
{
|
||||
// Clear reserve for high account.
|
||||
|
||||
mEngine->view ().ownerCountAdjust (uHighAccountID, -1, sleHighAccount);
|
||||
mEngine->view ().decrementOwnerCount (sleHighAccount);
|
||||
uFlagsOut &= ~lsfHighReserve;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user