mirror of
https://github.com/XRPLF/rippled.git
synced 2026-10-21 19:18:22 +00:00
Compare commits
19
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e67d1d4012 | ||
|
|
5b720dbbea | ||
|
|
5c28ad60c7 | ||
|
|
40e9512020 | ||
|
|
1f824cfcf2 | ||
|
|
a90a2cd5fe | ||
|
|
f406600031 | ||
|
|
5b9562556c | ||
|
|
c7aa4ea5ef | ||
|
|
510bd2305a | ||
|
|
6298cd8235 | ||
|
|
dd8da37dac | ||
|
|
617f490c58 | ||
|
|
4ea944e037 | ||
|
|
2978330bf9 | ||
|
|
d4acfcdb20 | ||
|
|
699d9b1656 | ||
|
|
a705d48033 | ||
|
|
0c743ea776 |
No files matched your search
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
@@ -8,8 +9,14 @@
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
template <typename ViewT>
|
||||
@@ -40,6 +47,165 @@ public:
|
||||
: Base(keylet::trustLine(id, issue), view, j)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the limit that @p account sets on this line for IOUs issued
|
||||
* by @p issuer. The issuer of the result is @p account.
|
||||
*
|
||||
* @param account the account whose limit is returned.
|
||||
* @param issuer the account on the other side of the line.
|
||||
* @return the limit @p account sets on this line.
|
||||
*/
|
||||
[[nodiscard]] STAmount
|
||||
creditLimit(AccountID const& account, AccountID const& issuer) const
|
||||
{
|
||||
STAmount result = (*this)->getFieldAmount(account < issuer ? sfLowLimit : sfHighLimit);
|
||||
result.get<Issue>().account = account;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of IOUs issued by @p issuer that @p account holds
|
||||
* on this line. The issuer of the result is @p account.
|
||||
*
|
||||
* @param account the account whose balance is returned.
|
||||
* @param issuer the account on the other side of the line.
|
||||
* @return the balance @p account holds on this line.
|
||||
*/
|
||||
[[nodiscard]] STAmount
|
||||
creditBalance(AccountID const& account, AccountID const& issuer) const
|
||||
{
|
||||
STAmount result = (*this)->getFieldAmount(sfBalance);
|
||||
if (account < issuer)
|
||||
result.negate();
|
||||
result.get<Issue>().account = account;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if @p issuer froze this line for @p account.
|
||||
*
|
||||
* @param account the account whose side of the line is checked.
|
||||
* @param issuer the account on the other side of the line.
|
||||
* @return true if @p issuer froze this line for @p account.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
isIndividualFrozen(AccountID const& account, AccountID const& issuer) const
|
||||
{
|
||||
return (*this)->isFlag((issuer > account) ? lsfHighFreeze : lsfLowFreeze);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if either side deep-froze this line.
|
||||
*
|
||||
* @return true if either side deep-froze this line.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
isDeepFrozen() const
|
||||
{
|
||||
return (*this)->isFlag(lsfHighDeepFreeze) || (*this)->isFlag(lsfLowDeepFreeze);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if @p issuer authorized @p account on this line.
|
||||
*
|
||||
* @note This checks only the line's auth flag. Whether the issuer
|
||||
* requires authorization (lsfRequireAuth) is on the issuer AccountRoot;
|
||||
* see requireAuth().
|
||||
*
|
||||
* @param account the account whose authorization is checked.
|
||||
* @param issuer the account on the other side of the line.
|
||||
* @return true if @p issuer authorized @p account on this line.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
isAuthorized(AccountID const& account, AccountID const& issuer) const
|
||||
{
|
||||
return (*this)->isFlag((account > issuer) ? lsfLowAuth : lsfHighAuth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes this line from the owner directories of @p lowAccount and
|
||||
* @p highAccount, clears both sponsors, and erases it.
|
||||
*
|
||||
* @param lowAccount the account on the low side of the line.
|
||||
* @param highAccount the account on the high side of the line.
|
||||
* @return tesSUCCESS, or tefBAD_LEDGER if a directory removal fails
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
removeFromLedger(AccountID const& lowAccount, AccountID const& highAccount)
|
||||
requires Base::kIsWritable;
|
||||
|
||||
/**
|
||||
* Create a trust line
|
||||
*
|
||||
* This can set an initial balance.
|
||||
*
|
||||
* @param view the view to apply the trust line creation to.
|
||||
* @param bSrcHigh true if the source account is the high side of the
|
||||
* line.
|
||||
* @param uSrcAccountID the account the balance and limit are set from.
|
||||
* @param uDstAccountID the other account on the line.
|
||||
* @param uIndex the ledger index of the new ripple state entry.
|
||||
* @param sleAccount the account being set (the high or low side,
|
||||
* depending on bSrcHigh and the limit's issuer).
|
||||
* @param bAuth whether to authorize the account.
|
||||
* @param bNoRipple whether to disable rippling through the account being
|
||||
* set.
|
||||
* @param bFreeze whether the account being set cannot have funds leave.
|
||||
* @param bDeepFreeze whether the account being set can neither send nor
|
||||
* receive funds.
|
||||
* @param saBalance the balance of the account being set; the issuer
|
||||
* should be noAccount().
|
||||
* @param saLimit the limit for the account being set; the issuer should
|
||||
* be the account being set.
|
||||
* @param uQualityIn the inbound quality for the account being set, or 0
|
||||
* to leave it unset.
|
||||
* @param uQualityOut the outbound quality for the account being set, or
|
||||
* 0 to leave it unset.
|
||||
* @param sponsorSle the sponsor to charge the new line's reserve to, if
|
||||
* any.
|
||||
* @param j the journal to log to.
|
||||
* @return tesSUCCESS, tecDIR_FULL if either owner directory is full,
|
||||
* tefINTERNAL if @p sleAccount is null, tecNO_TARGET if the peer account
|
||||
* does not exist, or tecINTERNAL if the line would be to self and the
|
||||
* lending protocol is enabled
|
||||
*/
|
||||
[[nodiscard]] static TER
|
||||
create(
|
||||
ApplyView& view,
|
||||
bool const bSrcHigh,
|
||||
AccountID const& uSrcAccountID,
|
||||
AccountID const& uDstAccountID,
|
||||
UInt256 const& uIndex, // --> ripple state entry
|
||||
SLE::Ref sleAccount, // --> the account being set.
|
||||
bool const bAuth, // --> authorize account.
|
||||
bool const bNoRipple, // --> others cannot ripple through
|
||||
bool const bFreeze, // --> funds cannot leave
|
||||
bool bDeepFreeze, // --> can neither receive nor send funds
|
||||
STAmount const& saBalance, // --> balance of account being set.
|
||||
// Issuer should be noAccount()
|
||||
STAmount const& saLimit, // --> limit for account being set.
|
||||
// Issuer should be the account being set.
|
||||
std::uint32_t uQualityIn,
|
||||
std::uint32_t uQualityOut,
|
||||
SLE::Ref sponsorSle,
|
||||
beast::Journal j)
|
||||
requires Base::kIsWritable;
|
||||
|
||||
/**
|
||||
* Removes this line if @p account holds no balance on it. Clears the
|
||||
* reserve flag and sponsor of each side that has a reserve, decreases
|
||||
* that side's owner count, and then calls removeFromLedger(). The
|
||||
* balance check is skipped when @p account is @p issuer.
|
||||
*
|
||||
* @param account the account whose balance is checked.
|
||||
* @param issuer the account on the other side of the line.
|
||||
* @return tesSUCCESS, tecHAS_OBLIGATIONS if the balance is not zero, or
|
||||
* tecINTERNAL / tefBAD_LEDGER on failure
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
removeIfEmpty(AccountID const& account, AccountID const& issuer)
|
||||
requires Base::kIsWritable;
|
||||
};
|
||||
|
||||
using RippleStateEntryR = RippleStateEntry<ReadView>;
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
#include <xrpl/ledger/helpers/SponsorHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
@@ -93,7 +93,7 @@ escrowUnlockApplyHelper<Issue>(
|
||||
STAmount initialBalance(issue);
|
||||
initialBalance.get<Issue>().account = noAccount();
|
||||
|
||||
if (TER const ter = trustCreate(
|
||||
if (TER const ter = RippleStateEntryW::create(
|
||||
ctx.view, // payment sandbox
|
||||
recvLow, // is dest low?
|
||||
issuer, // source
|
||||
@@ -149,7 +149,7 @@ escrowUnlockApplyHelper<Issue>(
|
||||
// of the funds
|
||||
if (!createAsset)
|
||||
{
|
||||
auto const sleRippleState = ctx.view.peek(trustLineKey);
|
||||
RippleStateEntryW const sleRippleState(trustLineKey, ctx.view, journal);
|
||||
if (!sleRippleState)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/IOUAmount.h>
|
||||
@@ -130,46 +130,6 @@ checkDeepFrozen(ReadView const& view, AccountID const& account, Issue const& iss
|
||||
return isDeepFrozen(view, account, issue) ? (TER)tecFROZEN : (TER)tesSUCCESS;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Trust line operations
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a trust line
|
||||
*
|
||||
* This can set an initial balance.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
trustCreate(
|
||||
ApplyView& view,
|
||||
bool const bSrcHigh,
|
||||
AccountID const& uSrcAccountID,
|
||||
AccountID const& uDstAccountID,
|
||||
UInt256 const& uIndex, // --> ripple state entry
|
||||
SLE::Ref sleAccount, // --> the account being set.
|
||||
bool const bAuth, // --> authorize account.
|
||||
bool const bNoRipple, // --> others cannot ripple through
|
||||
bool const bFreeze, // --> funds cannot leave
|
||||
bool bDeepFreeze, // --> can neither receive nor send funds
|
||||
STAmount const& saBalance, // --> balance of account being set.
|
||||
// Issuer should be noAccount()
|
||||
STAmount const& saLimit, // --> limit for account being set.
|
||||
// Issuer should be the account being set.
|
||||
std::uint32_t uQualityIn,
|
||||
std::uint32_t uQualityOut,
|
||||
SLE::Ref sponsorSle,
|
||||
beast::Journal j);
|
||||
|
||||
[[nodiscard]] TER
|
||||
trustDelete(
|
||||
ApplyView& view,
|
||||
SLE::Ref sleRippleState,
|
||||
AccountID const& uLowAccountID,
|
||||
AccountID const& uHighAccountID,
|
||||
beast::Journal j);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// IOU issuance/redemption
|
||||
@@ -270,7 +230,7 @@ removeEmptyHolding(
|
||||
[[nodiscard]] TER
|
||||
deleteAMMTrustLine(
|
||||
ApplyView& view,
|
||||
SLE::pointer sleState,
|
||||
RippleStateEntryW& sleState,
|
||||
std::optional<AccountID> const& ammAccountID,
|
||||
beast::Journal j);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
@@ -33,7 +34,7 @@ checkFreeze(
|
||||
}
|
||||
}
|
||||
|
||||
if (auto sle = view.read(keylet::trustLine(src, dst, currency)))
|
||||
if (RippleStateEntryR const sle(src, dst, currency, view); sle)
|
||||
{
|
||||
if (sle->isFlag((dst > src) ? lsfHighFreeze : lsfLowFreeze))
|
||||
{
|
||||
@@ -77,8 +78,8 @@ checkNoRipple(
|
||||
beast::Journal j)
|
||||
{
|
||||
// fetch the ripple lines into and out of this node
|
||||
auto sleIn = view.read(keylet::trustLine(prev, cur, currency));
|
||||
auto sleOut = view.read(keylet::trustLine(cur, next, currency));
|
||||
RippleStateEntryR const sleIn(prev, cur, currency, view);
|
||||
RippleStateEntryR const sleOut(cur, next, currency, view);
|
||||
|
||||
if (!sleIn || !sleOut)
|
||||
return terNO_LINE;
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
|
||||
#include <xrpl/ledger/helpers/SponsorHelpers.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
template <typename ViewT>
|
||||
TER
|
||||
RippleStateEntry<ViewT>::removeFromLedger(AccountID const& lowAccount, AccountID const& highAccount)
|
||||
requires Base::kIsWritable
|
||||
{
|
||||
auto& view = this->applyView();
|
||||
auto const j = this->journal();
|
||||
|
||||
// Detect legacy dirs.
|
||||
std::uint64_t const uLowNode = (*this)->getFieldU64(sfLowNode);
|
||||
std::uint64_t const uHighNode = (*this)->getFieldU64(sfHighNode);
|
||||
|
||||
JLOG(j.trace()) << "trustDelete: Deleting ripple line: low";
|
||||
|
||||
if (!view.dirRemove(keylet::ownerDir(lowAccount), uLowNode, (*this)->key(), false))
|
||||
{
|
||||
return tefBAD_LEDGER; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
JLOG(j.trace()) << "trustDelete: Deleting ripple line: high";
|
||||
|
||||
if (!view.dirRemove(keylet::ownerDir(highAccount), uHighNode, (*this)->key(), false))
|
||||
{
|
||||
return tefBAD_LEDGER; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
removeSponsorFromLedgerEntry(this->mutableRawSle(), sfHighSponsor);
|
||||
removeSponsorFromLedgerEntry(this->mutableRawSle(), sfLowSponsor);
|
||||
|
||||
JLOG(j.trace()) << "trustDelete: Deleting ripple line: state";
|
||||
this->erase();
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
template <typename ViewT>
|
||||
TER
|
||||
RippleStateEntry<ViewT>::create(
|
||||
ApplyView& view,
|
||||
bool const bSrcHigh,
|
||||
AccountID const& uSrcAccountID,
|
||||
AccountID const& uDstAccountID,
|
||||
UInt256 const& uIndex, // ripple state entry
|
||||
SLE::Ref sleAccount, // the account being set.
|
||||
bool const bAuth, // authorize account.
|
||||
bool const bNoRipple, // others cannot ripple through
|
||||
bool const bFreeze, // funds cannot leave
|
||||
bool bDeepFreeze, // can neither receive nor send funds
|
||||
STAmount const& saBalance, // balance of account being set.
|
||||
// Issuer should be noAccount()
|
||||
STAmount const& saLimit, // limit for account being set.
|
||||
// Issuer should be the account being set.
|
||||
std::uint32_t uQualityIn,
|
||||
std::uint32_t uQualityOut,
|
||||
SLE::Ref sponsorSle,
|
||||
beast::Journal j)
|
||||
requires Base::kIsWritable
|
||||
{
|
||||
JLOG(j.trace()) << "trustCreate: " << to_string(uSrcAccountID) << ", "
|
||||
<< to_string(uDstAccountID) << ", " << saBalance.getFullText();
|
||||
|
||||
auto const& uLowAccountID = !bSrcHigh ? uSrcAccountID : uDstAccountID;
|
||||
auto const& uHighAccountID = bSrcHigh ? uSrcAccountID : uDstAccountID;
|
||||
if (uLowAccountID == uHighAccountID)
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE("xrpl::trustCreate : trust line to self");
|
||||
if (view.rules().enabled(featureLendingProtocol))
|
||||
return tecINTERNAL;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
RippleStateEntry sleRippleState(Keylet(ltRIPPLE_STATE, uIndex), view, j);
|
||||
sleRippleState.newSLE();
|
||||
sleRippleState.insert();
|
||||
|
||||
auto lowNode = view.dirInsert(
|
||||
keylet::ownerDir(uLowAccountID), sleRippleState->key(), describeOwnerDir(uLowAccountID));
|
||||
|
||||
if (!lowNode)
|
||||
return tecDIR_FULL; // LCOV_EXCL_LINE
|
||||
|
||||
auto highNode = view.dirInsert(
|
||||
keylet::ownerDir(uHighAccountID), sleRippleState->key(), describeOwnerDir(uHighAccountID));
|
||||
|
||||
if (!highNode)
|
||||
return tecDIR_FULL; // LCOV_EXCL_LINE
|
||||
|
||||
bool const bSetDst = saLimit.getIssuer() == uDstAccountID;
|
||||
bool const bSetHigh = bSrcHigh ^ bSetDst;
|
||||
|
||||
XRPL_ASSERT(sleAccount, "xrpl::trustCreate : non-null SLE");
|
||||
if (!sleAccount)
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
XRPL_ASSERT(
|
||||
sleAccount->getAccountID(sfAccount) == (bSetHigh ? uHighAccountID : uLowAccountID),
|
||||
"xrpl::trustCreate : matching account ID");
|
||||
auto const slePeer = view.peek(keylet::account(bSetHigh ? uLowAccountID : uHighAccountID));
|
||||
if (!slePeer)
|
||||
return tecNO_TARGET;
|
||||
|
||||
// Remember deletion hints.
|
||||
sleRippleState->setFieldU64(sfLowNode, *lowNode);
|
||||
sleRippleState->setFieldU64(sfHighNode, *highNode);
|
||||
|
||||
sleRippleState->setFieldAmount(bSetHigh ? sfHighLimit : sfLowLimit, saLimit);
|
||||
sleRippleState->setFieldAmount(
|
||||
bSetHigh ? sfLowLimit : sfHighLimit,
|
||||
STAmount(Issue{saBalance.get<Issue>().currency, bSetDst ? uSrcAccountID : uDstAccountID}));
|
||||
|
||||
if (uQualityIn != 0u)
|
||||
sleRippleState->setFieldU32(bSetHigh ? sfHighQualityIn : sfLowQualityIn, uQualityIn);
|
||||
|
||||
if (uQualityOut != 0u)
|
||||
sleRippleState->setFieldU32(bSetHigh ? sfHighQualityOut : sfLowQualityOut, uQualityOut);
|
||||
|
||||
std::uint32_t uFlags = bSetHigh ? lsfHighReserve : lsfLowReserve;
|
||||
|
||||
if (bAuth)
|
||||
{
|
||||
uFlags |= (bSetHigh ? lsfHighAuth : lsfLowAuth);
|
||||
}
|
||||
if (bNoRipple)
|
||||
{
|
||||
uFlags |= (bSetHigh ? lsfHighNoRipple : lsfLowNoRipple);
|
||||
}
|
||||
if (bFreeze)
|
||||
{
|
||||
uFlags |= (bSetHigh ? lsfHighFreeze : lsfLowFreeze);
|
||||
}
|
||||
if (bDeepFreeze)
|
||||
{
|
||||
uFlags |= (bSetHigh ? lsfHighDeepFreeze : lsfLowDeepFreeze);
|
||||
}
|
||||
|
||||
if (!slePeer->isFlag(lsfDefaultRipple))
|
||||
{
|
||||
// The other side's default is no rippling
|
||||
uFlags |= (bSetHigh ? lsfLowNoRipple : lsfHighNoRipple);
|
||||
}
|
||||
|
||||
sleRippleState->setFieldU32(sfFlags, uFlags);
|
||||
increaseOwnerCount(view, sleAccount, sponsorSle, 1, j);
|
||||
|
||||
addSponsorToLedgerEntry(
|
||||
sleRippleState.mutableRawSle(), sponsorSle, bSetHigh ? sfHighSponsor : sfLowSponsor);
|
||||
|
||||
// ONLY: Create ripple balance.
|
||||
sleRippleState->setFieldAmount(sfBalance, bSetHigh ? -saBalance : saBalance);
|
||||
|
||||
view.creditHookIOU(uSrcAccountID, uDstAccountID, saBalance, saBalance.zeroed());
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
template <typename ViewT>
|
||||
TER
|
||||
RippleStateEntry<ViewT>::removeIfEmpty(AccountID const& account, AccountID const& issuer)
|
||||
requires Base::kIsWritable
|
||||
{
|
||||
auto& view = this->applyView();
|
||||
auto const j = this->journal();
|
||||
|
||||
bool const accountIsIssuer = account == issuer;
|
||||
if (!accountIsIssuer && (*this)->at(sfBalance)->iou() != beast::kZero)
|
||||
return tecHAS_OBLIGATIONS;
|
||||
|
||||
// Adjust the owner count(s)
|
||||
if ((*this)->isFlag(lsfLowReserve))
|
||||
{
|
||||
// Clear reserve for low account.
|
||||
auto sleLowAccount = view.peek(keylet::account((*this)->at(sfLowLimit)->getIssuer()));
|
||||
if (!sleLowAccount)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const currentLowSponsor =
|
||||
getLedgerEntryReserveSponsor(view, this->rawSle(), sfLowSponsor);
|
||||
|
||||
decreaseOwnerCount(view, sleLowAccount, currentLowSponsor, 1, j);
|
||||
// It's not really necessary to clear the reserve flag, since the line
|
||||
// is about to be deleted, but this will make the metadata reflect an
|
||||
// accurate state at the time of deletion.
|
||||
(*this)->clearFlag(lsfLowReserve);
|
||||
removeSponsorFromLedgerEntry(this->mutableRawSle(), sfLowSponsor);
|
||||
}
|
||||
|
||||
if ((*this)->isFlag(lsfHighReserve))
|
||||
{
|
||||
// Clear reserve for high account.
|
||||
auto sleHighAccount = view.peek(keylet::account((*this)->at(sfHighLimit)->getIssuer()));
|
||||
if (!sleHighAccount)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const currentHighSponsor =
|
||||
getLedgerEntryReserveSponsor(view, this->rawSle(), sfHighSponsor);
|
||||
|
||||
decreaseOwnerCount(view, sleHighAccount, currentHighSponsor, 1, j);
|
||||
// It's not really necessary to clear the reserve flag, since the line
|
||||
// is about to be deleted, but this will make the metadata reflect an
|
||||
// accurate state at the time of deletion.
|
||||
(*this)->clearFlag(lsfHighReserve);
|
||||
removeSponsorFromLedgerEntry(this->mutableRawSle(), sfHighSponsor);
|
||||
}
|
||||
|
||||
return this->removeFromLedger(
|
||||
(*this)->at(sfLowLimit)->getIssuer(), (*this)->at(sfHighLimit)->getIssuer());
|
||||
}
|
||||
|
||||
template class RippleStateEntry<ReadView>;
|
||||
template class RippleStateEntry<ApplyView>;
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/Sandbox.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
@@ -21,6 +22,7 @@
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/Keylet.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
@@ -556,7 +558,7 @@ ammLPHolds(
|
||||
auto const currency = ammLPTCurrency(asset1, asset2);
|
||||
STAmount amount;
|
||||
|
||||
auto const sle = view.read(keylet::trustLine(lpAccount, ammAccount, currency));
|
||||
RippleStateEntryR const sle(lpAccount, ammAccount, currency, view);
|
||||
if (!sle)
|
||||
{
|
||||
amount.clear(Issue{currency, ammAccount});
|
||||
@@ -646,7 +648,7 @@ ammAccountHolds(ReadView const& view, AccountID const& ammAccountID, Asset const
|
||||
}
|
||||
else if (
|
||||
auto const sle =
|
||||
view.read(keylet::trustLine(ammAccountID, issue.account, issue.currency));
|
||||
RippleStateEntryR(ammAccountID, issue.account, issue.currency, view);
|
||||
sle && !isFrozen(view, ammAccountID, issue.currency, issue.account))
|
||||
{
|
||||
STAmount amount = (*sle)[sfBalance];
|
||||
@@ -688,7 +690,8 @@ deleteAMMTrustLines(
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return {deleteAMMTrustLine(sb, sleItem, ammAccountID, j), SkipEntry::No};
|
||||
RippleStateEntryW line(Keylet(ltRIPPLE_STATE, sleItem->key()), sb, j);
|
||||
return {deleteAMMTrustLine(sb, line, ammAccountID, j), SkipEntry::No};
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
JLOG(j.error()) << "deleteAMMObjects: deleting non-trustline or non-MPT " << nodeType;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
@@ -841,7 +842,7 @@ tokenOfferCreatePreclaim(
|
||||
if (view.rules().enabled(featureNFTokenMintOffer))
|
||||
{
|
||||
if (nftIssuer != amount.getIssuer() &&
|
||||
!view.read(keylet::trustLine(nftIssuer, amount.get<Issue>())))
|
||||
!RippleStateEntryR(nftIssuer, amount.get<Issue>(), view))
|
||||
return tecNO_LINE;
|
||||
}
|
||||
else if (!view.exists(keylet::trustLine(nftIssuer, amount.get<Issue>())))
|
||||
@@ -1028,7 +1029,7 @@ checkTrustlineAuthorized(
|
||||
|
||||
if (issuerAccount->isFlag(lsfRequireAuth))
|
||||
{
|
||||
auto const trustLine = view.read(keylet::trustLine(id, issue.account, issue.currency));
|
||||
RippleStateEntryR const trustLine(id, issue.account, issue.currency, view);
|
||||
|
||||
if (!trustLine)
|
||||
{
|
||||
@@ -1078,7 +1079,7 @@ checkTrustlineDeepFrozen(
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
auto const trustLine = view.read(keylet::trustLine(id, issue.account, issue.currency));
|
||||
RippleStateEntryR const trustLine(id, issue.account, issue.currency, view);
|
||||
|
||||
if (!trustLine)
|
||||
{
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
|
||||
#include <xrpl/ledger/helpers/SponsorHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
@@ -48,13 +47,10 @@ creditLimit(
|
||||
{
|
||||
STAmount result(Issue{currency, account});
|
||||
|
||||
auto sleRippleState = view.read(keylet::trustLine(account, issuer, currency));
|
||||
RippleStateEntryR const sleRippleState(account, issuer, currency, view);
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
result = sleRippleState->getFieldAmount(account < issuer ? sfLowLimit : sfHighLimit);
|
||||
result.get<Issue>().account = account;
|
||||
}
|
||||
result = sleRippleState.creditLimit(account, issuer);
|
||||
|
||||
XRPL_ASSERT(result.getIssuer() == account, "xrpl::creditLimit : result issuer match");
|
||||
XRPL_ASSERT(
|
||||
@@ -79,15 +75,10 @@ creditBalance(
|
||||
{
|
||||
STAmount result(Issue{currency, account});
|
||||
|
||||
auto sleRippleState = view.read(keylet::trustLine(account, issuer, currency));
|
||||
RippleStateEntryR const sleRippleState(account, issuer, currency, view);
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
result = sleRippleState->getFieldAmount(sfBalance);
|
||||
if (account < issuer)
|
||||
result.negate();
|
||||
result.get<Issue>().account = account;
|
||||
}
|
||||
result = sleRippleState.creditBalance(account, issuer);
|
||||
|
||||
XRPL_ASSERT(result.getIssuer() == account, "xrpl::creditBalance : result issuer match");
|
||||
XRPL_ASSERT(
|
||||
@@ -115,8 +106,8 @@ isIndividualFrozen(
|
||||
if (issuer != account)
|
||||
{
|
||||
// Check if the issuer froze the line
|
||||
auto const sle = view.read(keylet::trustLine(account, issuer, currency));
|
||||
if (sle && sle->isFlag((issuer > account) ? lsfHighFreeze : lsfLowFreeze))
|
||||
RippleStateEntryR const sle(account, issuer, currency, view);
|
||||
if (sle && sle.isIndividualFrozen(account, issuer))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -139,8 +130,8 @@ isFrozen(
|
||||
if (issuer != account)
|
||||
{
|
||||
// Check if the issuer froze the line
|
||||
sle = view.read(keylet::trustLine(account, issuer, currency));
|
||||
if (sle && sle->isFlag((issuer > account) ? lsfHighFreeze : lsfLowFreeze))
|
||||
RippleStateEntryR const sleLine(account, issuer, currency, view);
|
||||
if (sleLine && sleLine.isIndividualFrozen(account, issuer))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -163,171 +154,13 @@ isDeepFrozen(
|
||||
return false;
|
||||
}
|
||||
|
||||
auto const sle = view.read(keylet::trustLine(account, issuer, currency));
|
||||
RippleStateEntryR const sle(account, issuer, currency, view);
|
||||
if (!sle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return sle->isFlag(lsfHighDeepFreeze) || sle->isFlag(lsfLowDeepFreeze);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Trust line operations
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
TER
|
||||
trustCreate(
|
||||
ApplyView& view,
|
||||
bool const bSrcHigh,
|
||||
AccountID const& uSrcAccountID,
|
||||
AccountID const& uDstAccountID,
|
||||
UInt256 const& uIndex, // ripple state entry
|
||||
SLE::Ref sleAccount, // the account being set.
|
||||
bool const bAuth, // authorize account.
|
||||
bool const bNoRipple, // others cannot ripple through
|
||||
bool const bFreeze, // funds cannot leave
|
||||
bool bDeepFreeze, // can neither receive nor send funds
|
||||
STAmount const& saBalance, // balance of account being set.
|
||||
// Issuer should be noAccount()
|
||||
STAmount const& saLimit, // limit for account being set.
|
||||
// Issuer should be the account being set.
|
||||
std::uint32_t uQualityIn,
|
||||
std::uint32_t uQualityOut,
|
||||
SLE::Ref sponsorSle,
|
||||
beast::Journal j)
|
||||
{
|
||||
JLOG(j.trace()) << "trustCreate: " << to_string(uSrcAccountID) << ", "
|
||||
<< to_string(uDstAccountID) << ", " << saBalance.getFullText();
|
||||
|
||||
auto const& uLowAccountID = !bSrcHigh ? uSrcAccountID : uDstAccountID;
|
||||
auto const& uHighAccountID = bSrcHigh ? uSrcAccountID : uDstAccountID;
|
||||
if (uLowAccountID == uHighAccountID)
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE("xrpl::trustCreate : trust line to self");
|
||||
if (view.rules().enabled(featureLendingProtocol))
|
||||
return tecINTERNAL;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
auto const sleRippleState = std::make_shared<SLE>(ltRIPPLE_STATE, uIndex);
|
||||
view.insert(sleRippleState);
|
||||
|
||||
auto lowNode = view.dirInsert(
|
||||
keylet::ownerDir(uLowAccountID), sleRippleState->key(), describeOwnerDir(uLowAccountID));
|
||||
|
||||
if (!lowNode)
|
||||
return tecDIR_FULL; // LCOV_EXCL_LINE
|
||||
|
||||
auto highNode = view.dirInsert(
|
||||
keylet::ownerDir(uHighAccountID), sleRippleState->key(), describeOwnerDir(uHighAccountID));
|
||||
|
||||
if (!highNode)
|
||||
return tecDIR_FULL; // LCOV_EXCL_LINE
|
||||
|
||||
bool const bSetDst = saLimit.getIssuer() == uDstAccountID;
|
||||
bool const bSetHigh = bSrcHigh ^ bSetDst;
|
||||
|
||||
XRPL_ASSERT(sleAccount, "xrpl::trustCreate : non-null SLE");
|
||||
if (!sleAccount)
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
XRPL_ASSERT(
|
||||
sleAccount->getAccountID(sfAccount) == (bSetHigh ? uHighAccountID : uLowAccountID),
|
||||
"xrpl::trustCreate : matching account ID");
|
||||
auto const slePeer = view.peek(keylet::account(bSetHigh ? uLowAccountID : uHighAccountID));
|
||||
if (!slePeer)
|
||||
return tecNO_TARGET;
|
||||
|
||||
// Remember deletion hints.
|
||||
sleRippleState->setFieldU64(sfLowNode, *lowNode);
|
||||
sleRippleState->setFieldU64(sfHighNode, *highNode);
|
||||
|
||||
sleRippleState->setFieldAmount(bSetHigh ? sfHighLimit : sfLowLimit, saLimit);
|
||||
sleRippleState->setFieldAmount(
|
||||
bSetHigh ? sfLowLimit : sfHighLimit,
|
||||
STAmount(Issue{saBalance.get<Issue>().currency, bSetDst ? uSrcAccountID : uDstAccountID}));
|
||||
|
||||
if (uQualityIn != 0u)
|
||||
sleRippleState->setFieldU32(bSetHigh ? sfHighQualityIn : sfLowQualityIn, uQualityIn);
|
||||
|
||||
if (uQualityOut != 0u)
|
||||
sleRippleState->setFieldU32(bSetHigh ? sfHighQualityOut : sfLowQualityOut, uQualityOut);
|
||||
|
||||
std::uint32_t uFlags = bSetHigh ? lsfHighReserve : lsfLowReserve;
|
||||
|
||||
if (bAuth)
|
||||
{
|
||||
uFlags |= (bSetHigh ? lsfHighAuth : lsfLowAuth);
|
||||
}
|
||||
if (bNoRipple)
|
||||
{
|
||||
uFlags |= (bSetHigh ? lsfHighNoRipple : lsfLowNoRipple);
|
||||
}
|
||||
if (bFreeze)
|
||||
{
|
||||
uFlags |= (bSetHigh ? lsfHighFreeze : lsfLowFreeze);
|
||||
}
|
||||
if (bDeepFreeze)
|
||||
{
|
||||
uFlags |= (bSetHigh ? lsfHighDeepFreeze : lsfLowDeepFreeze);
|
||||
}
|
||||
|
||||
if (!slePeer->isFlag(lsfDefaultRipple))
|
||||
{
|
||||
// The other side's default is no rippling
|
||||
uFlags |= (bSetHigh ? lsfLowNoRipple : lsfHighNoRipple);
|
||||
}
|
||||
|
||||
sleRippleState->setFieldU32(sfFlags, uFlags);
|
||||
increaseOwnerCount(view, sleAccount, sponsorSle, 1, j);
|
||||
|
||||
addSponsorToLedgerEntry(sleRippleState, sponsorSle, bSetHigh ? sfHighSponsor : sfLowSponsor);
|
||||
|
||||
// ONLY: Create ripple balance.
|
||||
sleRippleState->setFieldAmount(sfBalance, bSetHigh ? -saBalance : saBalance);
|
||||
|
||||
view.creditHookIOU(uSrcAccountID, uDstAccountID, saBalance, saBalance.zeroed());
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
trustDelete(
|
||||
ApplyView& view,
|
||||
SLE::Ref sleRippleState,
|
||||
AccountID const& uLowAccountID,
|
||||
AccountID const& uHighAccountID,
|
||||
beast::Journal j)
|
||||
{
|
||||
// Detect legacy dirs.
|
||||
std::uint64_t const uLowNode = sleRippleState->getFieldU64(sfLowNode);
|
||||
std::uint64_t const uHighNode = sleRippleState->getFieldU64(sfHighNode);
|
||||
|
||||
JLOG(j.trace()) << "trustDelete: Deleting ripple line: low";
|
||||
|
||||
if (!view.dirRemove(keylet::ownerDir(uLowAccountID), uLowNode, sleRippleState->key(), false))
|
||||
{
|
||||
return tefBAD_LEDGER; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
JLOG(j.trace()) << "trustDelete: Deleting ripple line: high";
|
||||
|
||||
if (!view.dirRemove(keylet::ownerDir(uHighAccountID), uHighNode, sleRippleState->key(), false))
|
||||
{
|
||||
return tefBAD_LEDGER; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
removeSponsorFromLedgerEntry(sleRippleState, sfHighSponsor);
|
||||
removeSponsorFromLedgerEntry(sleRippleState, sfLowSponsor);
|
||||
|
||||
JLOG(j.trace()) << "trustDelete: Deleting ripple line: state";
|
||||
view.erase(sleRippleState);
|
||||
|
||||
return tesSUCCESS;
|
||||
return sle.isDeepFrozen();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -339,7 +172,7 @@ trustDelete(
|
||||
static bool
|
||||
updateTrustLine(
|
||||
ApplyView& view,
|
||||
SLE::pointer state,
|
||||
RippleStateEntryW& state,
|
||||
bool bSenderHigh,
|
||||
AccountID const& sender,
|
||||
STAmount const& before,
|
||||
@@ -376,14 +209,15 @@ updateTrustLine(
|
||||
{
|
||||
// VFALCO Where is the line being deleted?
|
||||
// Clear the reserve of the sender, possibly delete the line!
|
||||
auto const currentSponsor =
|
||||
getLedgerEntryReserveSponsor(view, state, bSenderHigh ? sfHighSponsor : sfLowSponsor);
|
||||
auto const currentSponsor = getLedgerEntryReserveSponsor(
|
||||
view, state.rawSle(), bSenderHigh ? sfHighSponsor : sfLowSponsor);
|
||||
decreaseOwnerCount(view, sle, currentSponsor, 1, j);
|
||||
|
||||
// Clear reserve flag.
|
||||
state->clearFlag(senderReserveFlag);
|
||||
|
||||
removeSponsorFromLedgerEntry(state, !bSenderHigh ? sfLowSponsor : sfHighSponsor);
|
||||
removeSponsorFromLedgerEntry(
|
||||
state.mutableRawSle(), !bSenderHigh ? sfLowSponsor : sfHighSponsor);
|
||||
|
||||
// Balance is zero, receiver reserve is clear.
|
||||
if (!after && !state->isFlag(receiverReserveFlag))
|
||||
@@ -418,7 +252,7 @@ issueIOU(
|
||||
|
||||
auto const index = keylet::trustLine(issue.account, account, issue.currency);
|
||||
|
||||
if (auto state = view.peek(index))
|
||||
if (RippleStateEntryW state(index, view, j); state)
|
||||
{
|
||||
STAmount finalBalance = state->getFieldAmount(sfBalance);
|
||||
|
||||
@@ -443,15 +277,11 @@ issueIOU(
|
||||
state->setFieldAmount(sfBalance, finalBalance);
|
||||
if (mustDelete)
|
||||
{
|
||||
return trustDelete(
|
||||
view,
|
||||
state,
|
||||
bSenderHigh ? account : issue.account,
|
||||
bSenderHigh ? issue.account : account,
|
||||
j);
|
||||
return state.removeFromLedger(
|
||||
bSenderHigh ? account : issue.account, bSenderHigh ? issue.account : account);
|
||||
}
|
||||
|
||||
view.update(state);
|
||||
state.update();
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
@@ -470,7 +300,7 @@ issueIOU(
|
||||
|
||||
bool const noRipple = !receiverAccount->isFlag(lsfDefaultRipple);
|
||||
|
||||
return trustCreate(
|
||||
return RippleStateEntryW::create(
|
||||
view,
|
||||
bSenderHigh,
|
||||
issue.account,
|
||||
@@ -511,7 +341,7 @@ redeemIOU(
|
||||
|
||||
bool const bSenderHigh = account > issue.account;
|
||||
|
||||
if (auto state = view.peek(keylet::trustLine(account, issue.account, issue.currency)))
|
||||
if (RippleStateEntryW state(account, issue.account, issue.currency, view, j); state)
|
||||
{
|
||||
STAmount finalBalance = state->getFieldAmount(sfBalance);
|
||||
|
||||
@@ -537,15 +367,11 @@ redeemIOU(
|
||||
|
||||
if (mustDelete)
|
||||
{
|
||||
return trustDelete(
|
||||
view,
|
||||
state,
|
||||
bSenderHigh ? issue.account : account,
|
||||
bSenderHigh ? account : issue.account,
|
||||
j);
|
||||
return state.removeFromLedger(
|
||||
bSenderHigh ? issue.account : account, bSenderHigh ? account : issue.account);
|
||||
}
|
||||
|
||||
view.update(state);
|
||||
state.update();
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
@@ -572,7 +398,7 @@ requireAuth(ReadView const& view, Issue const& issue, AccountID const& account,
|
||||
if (isXRP(issue) || issue.account == account)
|
||||
return tesSUCCESS;
|
||||
|
||||
auto const trustLine = view.read(keylet::trustLine(account, issue.account, issue.currency));
|
||||
RippleStateEntryR const trustLine(account, issue.account, issue.currency, view);
|
||||
// If account has no line, and this is a strong check, fail
|
||||
if (!trustLine && authType == AuthType::StrongAuth)
|
||||
return tecNO_LINE;
|
||||
@@ -584,7 +410,7 @@ requireAuth(ReadView const& view, Issue const& issue, AccountID const& account,
|
||||
{
|
||||
if (trustLine)
|
||||
{
|
||||
if (trustLine->isFlag((account > issue.account) ? lsfLowAuth : lsfHighAuth))
|
||||
if (trustLine.isAuthorized(account, issue.account))
|
||||
return tesSUCCESS;
|
||||
|
||||
// A pseudo-account cannot submit transactions and only stores assets for the object
|
||||
@@ -616,7 +442,7 @@ canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, Acc
|
||||
auto const isRippleDisabled = [&](AccountID account) -> bool {
|
||||
// Line might not exist, but some transfers can create it. If this
|
||||
// is the case, just check the default ripple on the issuer account.
|
||||
auto const line = view.read(keylet::trustLine(account, issue));
|
||||
RippleStateEntryR const line(account, issue, view);
|
||||
if (line)
|
||||
{
|
||||
bool const issuerHigh = issuerId > account;
|
||||
@@ -700,7 +526,7 @@ addEmptyHolding(
|
||||
return ret;
|
||||
}
|
||||
|
||||
return trustCreate(
|
||||
return RippleStateEntryW::create(
|
||||
ctx.view,
|
||||
high,
|
||||
srcId,
|
||||
@@ -743,59 +569,16 @@ removeEmptyHolding(
|
||||
// If the account is the issuer, then no line should exist. Check anyway.
|
||||
// If a line does exist, it will get deleted. If not, return success.
|
||||
bool const accountIsIssuer = accountID == issue.account;
|
||||
auto const line = ctx.view.peek(keylet::trustLine(accountID, issue));
|
||||
RippleStateEntryW line(accountID, issue, ctx.view, journal);
|
||||
if (!line)
|
||||
return accountIsIssuer ? (TER)tesSUCCESS : (TER)tecOBJECT_NOT_FOUND;
|
||||
if (!accountIsIssuer && line->at(sfBalance)->iou() != beast::kZero)
|
||||
return tecHAS_OBLIGATIONS;
|
||||
|
||||
// Adjust the owner count(s)
|
||||
if (line->isFlag(lsfLowReserve))
|
||||
{
|
||||
// Clear reserve for low account.
|
||||
auto sleLowAccount = ctx.view.peek(keylet::account(line->at(sfLowLimit)->getIssuer()));
|
||||
if (!sleLowAccount)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const currentLowSponsor = getLedgerEntryReserveSponsor(ctx.view, line, sfLowSponsor);
|
||||
|
||||
decreaseOwnerCount(ctx.view, sleLowAccount, currentLowSponsor, 1, journal);
|
||||
// It's not really necessary to clear the reserve flag, since the line
|
||||
// is about to be deleted, but this will make the metadata reflect an
|
||||
// accurate state at the time of deletion.
|
||||
line->clearFlag(lsfLowReserve);
|
||||
removeSponsorFromLedgerEntry(line, sfLowSponsor);
|
||||
}
|
||||
|
||||
if (line->isFlag(lsfHighReserve))
|
||||
{
|
||||
// Clear reserve for high account.
|
||||
auto sleHighAccount = ctx.view.peek(keylet::account(line->at(sfHighLimit)->getIssuer()));
|
||||
if (!sleHighAccount)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const currentHighSponsor = getLedgerEntryReserveSponsor(ctx.view, line, sfHighSponsor);
|
||||
|
||||
decreaseOwnerCount(ctx.view, sleHighAccount, currentHighSponsor, 1, journal);
|
||||
// It's not really necessary to clear the reserve flag, since the line
|
||||
// is about to be deleted, but this will make the metadata reflect an
|
||||
// accurate state at the time of deletion.
|
||||
line->clearFlag(lsfHighReserve);
|
||||
removeSponsorFromLedgerEntry(line, sfHighSponsor);
|
||||
}
|
||||
|
||||
return trustDelete(
|
||||
ctx.view,
|
||||
line,
|
||||
line->at(sfLowLimit)->getIssuer(),
|
||||
line->at(sfHighLimit)->getIssuer(),
|
||||
journal);
|
||||
return line.removeIfEmpty(accountID, issue.account);
|
||||
}
|
||||
|
||||
TER
|
||||
deleteAMMTrustLine(
|
||||
ApplyView& view,
|
||||
SLE::pointer sleState,
|
||||
RippleStateEntryW& sleState,
|
||||
std::optional<AccountID> const& ammAccountID,
|
||||
beast::Journal j)
|
||||
{
|
||||
@@ -825,17 +608,21 @@ deleteAMMTrustLine(
|
||||
if (ammAccountID && (low != *ammAccountID && high != *ammAccountID))
|
||||
return terNO_AMM;
|
||||
|
||||
auto const sponsorSle =
|
||||
getLedgerEntryReserveSponsor(view, sleState, !ammLow ? sfLowSponsor : sfHighSponsor);
|
||||
auto const sponsorSle = getLedgerEntryReserveSponsor(
|
||||
view, sleState.rawSle(), !ammLow ? sfLowSponsor : sfHighSponsor);
|
||||
|
||||
if (auto const ter = trustDelete(view, sleState, low, high, j); !isTesSuccess(ter))
|
||||
// removeFromLedger() drops the entry's SLE, so read the reserve flag
|
||||
// first. removeFromLedger() does not change the flags.
|
||||
auto const uFlags = !ammLow ? lsfLowReserve : lsfHighReserve;
|
||||
bool const hasReserve = sleState->isFlag(uFlags);
|
||||
|
||||
if (auto const ter = sleState.removeFromLedger(low, high); !isTesSuccess(ter))
|
||||
{
|
||||
JLOG(j.error()) << "deleteAMMTrustLine: failed to delete the trustline.";
|
||||
return ter;
|
||||
}
|
||||
|
||||
auto const uFlags = !ammLow ? lsfLowReserve : lsfHighReserve;
|
||||
if (!sleState->isFlag(uFlags))
|
||||
if (!hasReserve)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
decreaseOwnerCount(view, !ammLow ? sleLow : sleHigh, sponsorSle, 1, j);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
@@ -32,6 +33,7 @@
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
@@ -265,7 +267,7 @@ checkDepositFreeze(
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static SLE::const_pointer
|
||||
static std::optional<RippleStateEntryR>
|
||||
getLineIfUsable(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
@@ -274,11 +276,11 @@ getLineIfUsable(
|
||||
FreezeHandling zeroIfFrozen,
|
||||
beast::Journal j)
|
||||
{
|
||||
auto sle = view.read(keylet::trustLine(account, issuer, currency));
|
||||
RippleStateEntryR sle(account, issuer, currency, view);
|
||||
|
||||
if (!sle)
|
||||
{
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (zeroIfFrozen == FreezeHandling::ZeroIfFrozen)
|
||||
@@ -286,7 +288,7 @@ getLineIfUsable(
|
||||
if (isFrozen(view, account, currency, issuer) ||
|
||||
isDeepFrozen(view, account, currency, issuer))
|
||||
{
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// when fixFrozenLPTokenTransfer is enabled, if currency is lptoken,
|
||||
@@ -296,7 +298,7 @@ getLineIfUsable(
|
||||
auto const sleIssuer = view.read(keylet::account(issuer));
|
||||
if (!sleIssuer)
|
||||
{
|
||||
return nullptr; // LCOV_EXCL_LINE
|
||||
return std::nullopt; // LCOV_EXCL_LINE
|
||||
}
|
||||
if (sleIssuer->isFieldPresent(sfAMMID))
|
||||
{
|
||||
@@ -305,7 +307,7 @@ getLineIfUsable(
|
||||
if (!sleAmm ||
|
||||
isLPTokenFrozen(view, account, (*sleAmm)[sfAsset], (*sleAmm)[sfAsset2]))
|
||||
{
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -316,7 +318,7 @@ getLineIfUsable(
|
||||
// gated by featureMPTokensV2.
|
||||
if (!isTesSuccess(canTransferLPToken(view, account, account, issuer)))
|
||||
{
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,7 +328,7 @@ getLineIfUsable(
|
||||
static STAmount
|
||||
getTrustLineBalance(
|
||||
ReadView const& view,
|
||||
SLE::ConstRef sle,
|
||||
std::optional<RippleStateEntryR> const& sle,
|
||||
AccountID const& account,
|
||||
Currency const& currency,
|
||||
AccountID const& issuer,
|
||||
@@ -336,7 +338,7 @@ getTrustLineBalance(
|
||||
STAmount amount;
|
||||
if (sle)
|
||||
{
|
||||
amount = sle->getFieldAmount(sfBalance);
|
||||
amount = (*sle)->getFieldAmount(sfBalance);
|
||||
bool const accountHigh = account > issuer;
|
||||
auto const& oppositeField = accountHigh ? sfLowLimit : sfHighLimit;
|
||||
if (accountHigh)
|
||||
@@ -346,7 +348,7 @@ getTrustLineBalance(
|
||||
}
|
||||
if (includeOppositeLimit)
|
||||
{
|
||||
amount += sle->getFieldAmount(oppositeField);
|
||||
amount += (*sle)->getFieldAmount(oppositeField);
|
||||
}
|
||||
amount.get<Issue>().account = issuer;
|
||||
}
|
||||
@@ -386,7 +388,7 @@ accountHolds(
|
||||
}
|
||||
|
||||
// IOU: Return balance on trust line modulo freeze
|
||||
SLE::const_pointer const sle =
|
||||
std::optional<RippleStateEntryR> const sle =
|
||||
getLineIfUsable(view, account, currency, issuer, zeroIfFrozen, j);
|
||||
|
||||
return getTrustLineBalance(view, sle, account, currency, issuer, returnSpendable, j);
|
||||
@@ -713,7 +715,7 @@ directSendNoFeeIOU(
|
||||
"xrpl::directSendNoFeeIOU : receiver is not XRP");
|
||||
|
||||
// If the line exists, modify it accordingly.
|
||||
if (auto const sleRippleState = view.peek(index))
|
||||
if (RippleStateEntryW sleRippleState(index, view, j); sleRippleState)
|
||||
{
|
||||
STAmount saBalance = sleRippleState->getFieldAmount(sfBalance);
|
||||
|
||||
@@ -759,11 +761,11 @@ directSendNoFeeIOU(
|
||||
{
|
||||
// Clear the reserve of the sender, possibly delete the line!
|
||||
auto const currentSponsor = getLedgerEntryReserveSponsor(
|
||||
view, sleRippleState, !bSenderHigh ? sfLowSponsor : sfHighSponsor);
|
||||
view, sleRippleState.rawSle(), !bSenderHigh ? sfLowSponsor : sfHighSponsor);
|
||||
decreaseOwnerCount(view, view.peek(keylet::account(uSenderID)), currentSponsor, 1, j);
|
||||
|
||||
removeSponsorFromLedgerEntry(
|
||||
sleRippleState, !bSenderHigh ? sfLowSponsor : sfHighSponsor);
|
||||
sleRippleState.mutableRawSle(), !bSenderHigh ? sfLowSponsor : sfHighSponsor);
|
||||
|
||||
// Clear reserve flag.
|
||||
sleRippleState->clearFlag(senderReserveFlag);
|
||||
@@ -783,15 +785,11 @@ directSendNoFeeIOU(
|
||||
|
||||
if (bDelete)
|
||||
{
|
||||
return trustDelete(
|
||||
view,
|
||||
sleRippleState,
|
||||
bSenderHigh ? uReceiverID : uSenderID,
|
||||
bSenderHigh ? uSenderID : uReceiverID,
|
||||
j);
|
||||
return sleRippleState.removeFromLedger(
|
||||
bSenderHigh ? uReceiverID : uSenderID, bSenderHigh ? uSenderID : uReceiverID);
|
||||
}
|
||||
|
||||
view.update(sleRippleState);
|
||||
sleRippleState.update();
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
@@ -811,7 +809,7 @@ directSendNoFeeIOU(
|
||||
|
||||
bool const noRipple = !sleAccount->isFlag(lsfDefaultRipple);
|
||||
|
||||
return trustCreate(
|
||||
return RippleStateEntryW::create(
|
||||
view,
|
||||
bSenderHigh,
|
||||
uSenderID,
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <xrpl/json/to_string.h> // IWYU pragma: keep
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/CredentialHelpers.h>
|
||||
#include <xrpl/ledger/helpers/DelegateHelpers.h>
|
||||
@@ -1277,7 +1278,7 @@ removeDeletedTrustLines(
|
||||
|
||||
for (auto const& index : trustLines)
|
||||
{
|
||||
if (auto const sleState = view.peek({ltRIPPLE_STATE, index});
|
||||
if (RippleStateEntryW sleState(Keylet(ltRIPPLE_STATE, index), view, viewJ);
|
||||
!isTesSuccess(deleteAMMTrustLine(view, sleState, std::nullopt, viewJ)))
|
||||
{
|
||||
JLOG(viewJ.error()) << "removeDeletedTrustLines: failed to delete AMM trustline";
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/PaymentSandbox.h>
|
||||
#include <xrpl/ledger/Sandbox.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AMMHelpers.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
@@ -1449,7 +1450,7 @@ BookStep<TIn, TOut, TDerived>::check(StrandContext const& ctx) const
|
||||
|
||||
auto const err = book_.in.visit(
|
||||
[&](Issue const& issue) -> std::optional<TER> {
|
||||
auto sle = view.read(keylet::trustLine(*prev, cur, issue.currency));
|
||||
RippleStateEntryR const sle(*prev, cur, issue.currency, view);
|
||||
if (!sle)
|
||||
return terNO_LINE;
|
||||
if (sle->isFlag((cur > *prev) ? lsfHighNoRipple : lsfLowNoRipple))
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/PaymentSandbox.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
@@ -345,7 +346,7 @@ DirectIPaymentStep::quality(ReadView const& sb, QualityDirection qDir) const
|
||||
if (src_ == dst_)
|
||||
return QUALITY_ONE;
|
||||
|
||||
auto const sle = sb.read(keylet::trustLine(dst_, src_, currency_));
|
||||
RippleStateEntryR const sle(dst_, src_, currency_, sb);
|
||||
|
||||
if (!sle)
|
||||
return QUALITY_ONE;
|
||||
@@ -421,7 +422,7 @@ DirectIPaymentStep::check(StrandContext const& ctx, SLE::ConstRef sleSrc) const
|
||||
// Since this is a payment a trust line must be present. Perform all
|
||||
// trust line related checks.
|
||||
{
|
||||
auto const sleLine = ctx.view.read(keylet::trustLine(src_, dst_, currency_));
|
||||
RippleStateEntryR const sleLine(src_, dst_, currency_, ctx.view);
|
||||
if (!sleLine)
|
||||
{
|
||||
JLOG(j_.trace()) << "DirectStepI: No credit line. " << *this;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/PaymentSandbox.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
@@ -198,8 +199,7 @@ CheckCash::preclaim(PreclaimContext const& ctx)
|
||||
return value.asset().visit(
|
||||
[&](Issue const& issue) -> TER {
|
||||
Currency const currency{issue.currency};
|
||||
auto const sleTrustLine =
|
||||
ctx.view.read(keylet::trustLine(dstId, issuerId, currency));
|
||||
RippleStateEntryR const sleTrustLine(dstId, issuerId, currency, ctx.view);
|
||||
|
||||
auto const sleIssuer = ctx.view.read(keylet::account(issuerId));
|
||||
if (!sleIssuer)
|
||||
@@ -471,7 +471,7 @@ CheckCash::doApply()
|
||||
STAmount initialBalance(flowDeliver.asset());
|
||||
initialBalance.get<Issue>().account = noAccount();
|
||||
|
||||
if (TER const ter = trustCreate(
|
||||
if (TER const ter = RippleStateEntryW::create(
|
||||
psb, // payment sandbox
|
||||
destLow, // is dest low?
|
||||
deliverIssuer, // source
|
||||
@@ -506,7 +506,7 @@ CheckCash::doApply()
|
||||
// would exceed the limit on their trust line. So we
|
||||
// tweak the trust line limits before calling flow and
|
||||
// then restore the trust line limits afterwards.
|
||||
auto const sleTrustLine = psb.peek(*trustLineKey);
|
||||
RippleStateEntryW sleTrustLine(*trustLineKey, psb, j_);
|
||||
if (!sleTrustLine)
|
||||
return tecNO_LINE;
|
||||
|
||||
@@ -552,7 +552,7 @@ CheckCash::doApply()
|
||||
if (trustLineKey)
|
||||
{
|
||||
SF_AMOUNT const& tweakedLimit = destLow ? sfLowLimit : sfHighLimit;
|
||||
if (auto const sleTrustLine = psb.peek(*trustLineKey))
|
||||
if (RippleStateEntryW sleTrustLine(*trustLineKey, psb); sleTrustLine)
|
||||
sleTrustLine->at(tweakedLimit) = savedLimit;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
@@ -126,8 +127,7 @@ CheckCreate::preclaim(PreclaimContext const& ctx)
|
||||
if (issuerId != srcId)
|
||||
{
|
||||
// Check if the issuer froze the line
|
||||
auto const sleTrust =
|
||||
ctx.view.read(keylet::trustLine(srcId, issuerId, issue.currency));
|
||||
RippleStateEntryR const sleTrust(srcId, issuerId, issue.currency, ctx.view);
|
||||
if (sleTrust &&
|
||||
sleTrust->isFlag((issuerId > srcId) ? lsfHighFreeze : lsfLowFreeze))
|
||||
{
|
||||
@@ -138,8 +138,7 @@ CheckCreate::preclaim(PreclaimContext const& ctx)
|
||||
if (issuerId != dstId)
|
||||
{
|
||||
// Check if dst froze the line.
|
||||
auto const sleTrust =
|
||||
ctx.view.read(keylet::trustLine(issuerId, dstId, issue.currency));
|
||||
RippleStateEntryR const sleTrust(issuerId, dstId, issue.currency, ctx.view);
|
||||
if (sleTrust &&
|
||||
sleTrust->isFlag((dstId > issuerId) ? lsfHighFreeze : lsfLowFreeze))
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/Sandbox.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AMMHelpers.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
@@ -275,7 +276,7 @@ applyCreate(ApplyContext& ctx, Sandbox& sb, AccountID const& account, beast::Jou
|
||||
|
||||
// LP Token already exists. (should not happen)
|
||||
auto const lptIss = ammLPTIssue(amount.asset(), amount2.asset(), accountId);
|
||||
if (sb.read(keylet::trustLine(accountId, lptIss)))
|
||||
if (RippleStateEntryR(accountId, lptIss, sb))
|
||||
{
|
||||
JLOG(j.error()) << "AMM Instance: LP Token already exists.";
|
||||
return {tecDUPLICATE, false};
|
||||
@@ -358,8 +359,7 @@ applyCreate(ApplyContext& ctx, Sandbox& sb, AccountID const& account, beast::Jou
|
||||
// Set AMM flag on AMM trustline
|
||||
if (!isXRP(amount))
|
||||
{
|
||||
SLE::pointer const sleRippleState =
|
||||
sb.peek(keylet::trustLine(accountId, issue));
|
||||
RippleStateEntryW sleRippleState(accountId, issue, sb, j);
|
||||
if (!sleRippleState)
|
||||
{
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
@@ -367,7 +367,7 @@ applyCreate(ApplyContext& ctx, Sandbox& sb, AccountID const& account, beast::Jou
|
||||
|
||||
auto const flags = sleRippleState->getFlags();
|
||||
sleRippleState->setFieldU32(sfFlags, flags | lsfAMMNode);
|
||||
sb.update(sleRippleState);
|
||||
sleRippleState.update();
|
||||
}
|
||||
return tesSUCCESS;
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/Sandbox.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AMMHelpers.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
@@ -233,8 +234,7 @@ AMMDeposit::preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
auto const lpIssue = (*ammSle)[sfLPTokenBalance].get<Issue>();
|
||||
// Adjust the reserve if LP doesn't have LPToken trustline
|
||||
auto const sle =
|
||||
ctx.view.read(keylet::trustLine(accountID, lpIssue.account, lpIssue.currency));
|
||||
RippleStateEntryR const sle(accountID, lpIssue.account, lpIssue.currency, ctx.view);
|
||||
if (xrpLiquid(ctx.view, accountID, !sle, ctx.j) >= deposit)
|
||||
return TER(tesSUCCESS);
|
||||
if (sle)
|
||||
@@ -584,8 +584,7 @@ AMMDeposit::deposit(
|
||||
{
|
||||
auto const& lpIssue = lpTokensDeposit.get<Issue>();
|
||||
// Adjust the reserve if LP doesn't have LPToken trustline
|
||||
auto const sle =
|
||||
view.read(keylet::trustLine(accountID_, lpIssue.account, lpIssue.currency));
|
||||
RippleStateEntryR const sle(accountID_, lpIssue.account, lpIssue.currency, view);
|
||||
if (xrpLiquid(view, accountID_, !sle, j_) >= depositAmount)
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <xrpl/ledger/PaymentSandbox.h>
|
||||
#include <xrpl/ledger/Sandbox.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/CredentialHelpers.h>
|
||||
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
|
||||
@@ -307,7 +308,7 @@ OfferCreate::checkAcceptAsset(
|
||||
return asset.visit(
|
||||
[&](Issue const& issue) -> TER {
|
||||
auto const& issuer = issue.getIssuer();
|
||||
auto const trustLine = view.read(keylet::trustLine(id, issuer, issue.currency));
|
||||
RippleStateEntryR const trustLine(id, issuer, issue.currency, view);
|
||||
|
||||
// Check if the issuer has lsfDisallowIncomingTrustline set.
|
||||
// If so, the account must already have a trustline to receive tokens.
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
@@ -214,7 +215,7 @@ escrowCreatePreclaimHelper<Issue>(
|
||||
return tecNO_PERMISSION;
|
||||
|
||||
// If the account does not have a trustline to the issuer, return tecNO_LINE
|
||||
auto const sleRippleState = ctx.view.read(keylet::trustLine(account, issuer, issue.currency));
|
||||
RippleStateEntryR const sleRippleState(account, issuer, issue.currency, ctx.view);
|
||||
if (!sleRippleState)
|
||||
return tecNO_LINE;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/NFTokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
@@ -317,7 +318,7 @@ NFTokenAcceptOffer::preclaim(PreclaimContext const& ctx)
|
||||
if (ctx.view.rules().enabled(fixEnforceNFTokenTrustline) &&
|
||||
(nft::getFlags(tokenID) & nft::kFlagCreateTrustLines) == 0 &&
|
||||
nftMinter != amount.getIssuer() &&
|
||||
!ctx.view.read(keylet::trustLine(nftMinter, amount.get<Issue>())))
|
||||
!RippleStateEntryR(nftMinter, amount.get<Issue>(), ctx.view))
|
||||
return tecNO_LINE;
|
||||
|
||||
// Check that the issuer is allowed to receive IOUs.
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/ledger/PaymentSandbox.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/CredentialHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
@@ -329,7 +330,7 @@ Payment::checkGranularSemantics(
|
||||
if (issue.getIssuer() != account && issue.getIssuer() != destination)
|
||||
return terNO_DELEGATE_PERMISSION;
|
||||
|
||||
auto const sle = view.read(keylet::trustLine(account, destination, issue.currency));
|
||||
RippleStateEntryR const sle(account, destination, issue.currency, view);
|
||||
if (!sle)
|
||||
return terNO_DELEGATE_PERMISSION;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
@@ -108,8 +109,8 @@ preclaimHelper<Issue>(
|
||||
if (!sleIssuer.isFlag(lsfAllowTrustLineClawback) || sleIssuer.isFlag(lsfNoFreeze))
|
||||
return tecNO_PERMISSION;
|
||||
|
||||
auto const sleRippleState =
|
||||
ctx.view.read(keylet::trustLine(holder, issuer, clawAmount.get<Issue>().currency));
|
||||
RippleStateEntryR const sleRippleState(
|
||||
holder, issuer, clawAmount.get<Issue>().currency, ctx.view);
|
||||
if (!sleRippleState)
|
||||
return tecNO_LINE;
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
#include <xrpl/ledger/helpers/SponsorHelpers.h>
|
||||
#include <xrpl/protocol/AMMCore.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
@@ -129,9 +129,8 @@ TrustSet::checkGranularSemantics(
|
||||
std::unordered_set<GranularPermissionType> const& heldGranularPermissions)
|
||||
{
|
||||
auto const saLimitAmount = tx.getFieldAmount(sfLimitAmount);
|
||||
auto const sleRippleState = view.read(
|
||||
keylet::trustLine(
|
||||
tx[sfAccount], saLimitAmount.getIssuer(), saLimitAmount.get<Issue>().currency));
|
||||
RippleStateEntryR const sleRippleState(
|
||||
tx[sfAccount], saLimitAmount.getIssuer(), saLimitAmount.get<Issue>().currency, view);
|
||||
|
||||
// granular permissions are not allowed to create a trustline
|
||||
if (!sleRippleState)
|
||||
@@ -258,7 +257,7 @@ TrustSet::preclaim(PreclaimContext const& ctx)
|
||||
|
||||
bool const bHigh = id > uDstAccountID;
|
||||
// Fetching current state of trust line
|
||||
auto const sleRippleState = ctx.view.read(keylet::trustLine(id, uDstAccountID, currency));
|
||||
RippleStateEntryR const sleRippleState(id, uDstAccountID, currency, ctx.view);
|
||||
std::uint32_t uFlags = sleRippleState ? sleRippleState->getFieldU32(sfFlags) : 0u;
|
||||
// Computing expected trust line state
|
||||
uFlags = computeFreezeFlags(
|
||||
@@ -361,8 +360,7 @@ TrustSet::doApply()
|
||||
STAmount saLimitAllow = saLimitAmount;
|
||||
saLimitAllow.get<Issue>().account = accountID_;
|
||||
|
||||
SLE::pointer const sleRippleState =
|
||||
view().peek(keylet::trustLine(accountID_, uDstAccountID, currency));
|
||||
RippleStateEntryW sleRippleState(accountID_, uDstAccountID, currency, view(), viewJ);
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
@@ -519,9 +517,9 @@ TrustSet::doApply()
|
||||
bool bReserveIncrease = false;
|
||||
|
||||
auto const currentHighSponsor =
|
||||
getLedgerEntryReserveSponsor(view(), sleRippleState, sfHighSponsor);
|
||||
getLedgerEntryReserveSponsor(view(), sleRippleState.rawSle(), sfHighSponsor);
|
||||
auto const currentLowSponsor =
|
||||
getLedgerEntryReserveSponsor(view(), sleRippleState, sfLowSponsor);
|
||||
getLedgerEntryReserveSponsor(view(), sleRippleState.rawSle(), sfLowSponsor);
|
||||
|
||||
if (bSetAuth)
|
||||
{
|
||||
@@ -552,7 +550,7 @@ TrustSet::doApply()
|
||||
increaseOwnerCount(view(), sleLowAccount, lowSponsor, 1, viewJ);
|
||||
uFlagsOut |= lsfLowReserve;
|
||||
|
||||
addSponsorToLedgerEntry(sleRippleState, lowSponsor, sfLowSponsor);
|
||||
addSponsorToLedgerEntry(sleRippleState.mutableRawSle(), lowSponsor, sfLowSponsor);
|
||||
|
||||
if (!bHigh)
|
||||
bReserveIncrease = true;
|
||||
@@ -564,7 +562,7 @@ TrustSet::doApply()
|
||||
decreaseOwnerCount(view(), sleLowAccount, currentLowSponsor, 1, viewJ);
|
||||
uFlagsOut &= ~lsfLowReserve;
|
||||
|
||||
removeSponsorFromLedgerEntry(sleRippleState, sfLowSponsor);
|
||||
removeSponsorFromLedgerEntry(sleRippleState.mutableRawSle(), sfLowSponsor);
|
||||
}
|
||||
|
||||
if (bHighReserveSet && !bHighReserved)
|
||||
@@ -594,7 +592,7 @@ TrustSet::doApply()
|
||||
increaseOwnerCount(view(), sleHighAccount, highSponsor, 1, viewJ);
|
||||
uFlagsOut |= lsfHighReserve;
|
||||
|
||||
addSponsorToLedgerEntry(sleRippleState, highSponsor, sfHighSponsor);
|
||||
addSponsorToLedgerEntry(sleRippleState.mutableRawSle(), highSponsor, sfHighSponsor);
|
||||
|
||||
if (bHigh)
|
||||
bReserveIncrease = true;
|
||||
@@ -606,7 +604,7 @@ TrustSet::doApply()
|
||||
decreaseOwnerCount(view(), sleHighAccount, currentHighSponsor, 1, viewJ);
|
||||
uFlagsOut &= ~lsfHighReserve;
|
||||
|
||||
removeSponsorFromLedgerEntry(sleRippleState, sfHighSponsor);
|
||||
removeSponsorFromLedgerEntry(sleRippleState.mutableRawSle(), sfHighSponsor);
|
||||
}
|
||||
|
||||
if (uFlagsIn != uFlagsOut)
|
||||
@@ -618,8 +616,7 @@ TrustSet::doApply()
|
||||
{
|
||||
// Delete.
|
||||
|
||||
terResult =
|
||||
trustDelete(view(), sleRippleState, uLowAccountID, uHighAccountID, viewJ);
|
||||
terResult = sleRippleState.removeFromLedger(uLowAccountID, uHighAccountID);
|
||||
}
|
||||
// Reserve is not scaled by load
|
||||
else if (
|
||||
@@ -642,7 +639,7 @@ TrustSet::doApply()
|
||||
}
|
||||
else
|
||||
{
|
||||
view().update(sleRippleState);
|
||||
sleRippleState.update();
|
||||
|
||||
JLOG(j_.trace()) << "Modify ripple line";
|
||||
}
|
||||
@@ -653,8 +650,7 @@ TrustSet::doApply()
|
||||
{
|
||||
// Delete.
|
||||
|
||||
terResult =
|
||||
trustDelete(view(), sleRippleState, uLowAccountID, uHighAccountID, viewJ);
|
||||
terResult = sleRippleState.removeFromLedger(uLowAccountID, uHighAccountID);
|
||||
}
|
||||
// Reserve is not scaled by load.
|
||||
else if (bReserveIncrease && preFeeBalance_ < reserveCreate)
|
||||
@@ -668,7 +664,7 @@ TrustSet::doApply()
|
||||
}
|
||||
else
|
||||
{
|
||||
view().update(sleRippleState);
|
||||
sleRippleState.update();
|
||||
|
||||
JLOG(j_.trace()) << "Modify ripple line";
|
||||
}
|
||||
@@ -725,7 +721,7 @@ TrustSet::doApply()
|
||||
JLOG(j_.trace()) << "doTrustSet: Creating ripple line: " << to_string(k.key);
|
||||
|
||||
// Create a new ripple line.
|
||||
terResult = trustCreate(
|
||||
terResult = RippleStateEntryW::create(
|
||||
view(),
|
||||
bHigh,
|
||||
accountID_,
|
||||
|
||||
@@ -252,7 +252,10 @@ class TheoreticalQuality_test : public beast::unit_test::Suite
|
||||
std::shared_ptr<ReadView const> closed,
|
||||
std::optional<Quality> const& expectedQ = {})
|
||||
{
|
||||
PaymentSandbox const sb(closed.get(), TapNone);
|
||||
// Not const: read-only ledger entries peek() through an ApplyView, which
|
||||
// is undefined behavior on a const object (see SLEBase.h).
|
||||
// NOLINTNEXTLINE(misc-const-correctness)
|
||||
PaymentSandbox sb(closed.get(), TapNone);
|
||||
AMMContext ammContext(rcp.srcAccount, false);
|
||||
|
||||
auto const sendMaxIssue = [&rcp]() -> std::optional<Asset> {
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/OpenView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/entries/RippleStateEntry.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
@@ -380,7 +380,7 @@ class InvariantsMisc_test : public InvariantsBase
|
||||
for (auto const& trustKeylet :
|
||||
{keylet::trustLine(ammAcctID, a1["USD"]), keylet::trustLine(a1, ammIssue)})
|
||||
{
|
||||
auto const line = ac.view().peek(trustKeylet);
|
||||
RippleStateEntryW line(trustKeylet, ac.view(), ac.journal);
|
||||
if (!line)
|
||||
{
|
||||
return false;
|
||||
@@ -389,12 +389,8 @@ class InvariantsMisc_test : public InvariantsBase
|
||||
STAmount const lowLimit = line->at(sfLowLimit);
|
||||
STAmount const highLimit = line->at(sfHighLimit);
|
||||
BEAST_EXPECT(
|
||||
trustDelete(
|
||||
ac.view(),
|
||||
line,
|
||||
lowLimit.getIssuer(),
|
||||
highLimit.getIssuer(),
|
||||
ac.journal) == tesSUCCESS);
|
||||
line.removeFromLedger(lowLimit.getIssuer(), highLimit.getIssuer()) ==
|
||||
tesSUCCESS);
|
||||
}
|
||||
|
||||
auto const ammSle = ac.view().peek(keylet::amm(ammKey));
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <xrpl/ledger/entries/XChainOwnedClaimIDEntry.h> // IWYU pragma: keep
|
||||
#include <xrpl/ledger/entries/XChainOwnedCreateAccountClaimIDEntry.h> // IWYU pragma: keep
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/Keylet.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
@@ -76,12 +77,22 @@ template class SLEBase<ApplyView>;
|
||||
#pragma push_macro("LEDGER_ENTRY")
|
||||
#undef LEDGER_ENTRY
|
||||
|
||||
// No explicit instantiation here, neither a definition nor a declaration.
|
||||
// A definition would instantiate an entry a second time once its member
|
||||
// bodies live in its own .cpp (MSVC rejects that with C4661 under /WX), and a
|
||||
// declaration (`extern template`) stops clang from emitting the inline
|
||||
// constructors of the header-only entries at -O0, which leaves them undefined
|
||||
// at link time in the debug builds. Naming the class in a static_assert is
|
||||
// enough to instantiate its definition, which is all this exhaustiveness
|
||||
// check needs; the per-type suites exercise the members.
|
||||
#define LEDGER_ENTRY(tag, value, name, ...) \
|
||||
template class name##Entry<ReadView>; \
|
||||
template class name##Entry<ApplyView>; \
|
||||
static_assert( \
|
||||
name##Entry<ReadView>::kEntryType == tag && name##Entry<ApplyView>::kEntryType == tag, \
|
||||
#name "Entry must be bound to " #tag);
|
||||
#name "Entry must be bound to " #tag); \
|
||||
static_assert( \
|
||||
std::is_constructible_v<name##Entry<ReadView>, Keylet const&, ReadView const&> && \
|
||||
std::is_constructible_v<name##Entry<ApplyView>, Keylet const&, ApplyView&>, \
|
||||
#name "Entry must be constructible from a Keylet and a view");
|
||||
|
||||
#include <xrpl/protocol/detail/ledger_entries.macro>
|
||||
|
||||
|
||||
Reference in new issue
Block a user