This commit is contained in:
Mayukha Vadari
2026-07-10 10:51:08 -04:00
parent fb9b10fc03
commit 9d11ba0ca7
57 changed files with 654 additions and 533 deletions

View File

@@ -12,6 +12,7 @@
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/AccountID.h>
@@ -555,7 +556,7 @@ ammLPHolds(
auto const currency = ammLPTCurrency(asset1, asset2);
STAmount amount;
auto const sle = view.read(keylet::trustLine(lpAccount, ammAccount, currency));
RippleStateEntry<ReadView> const sle{keylet::trustLine(lpAccount, ammAccount, currency), view};
if (!sle)
{
amount.clear(Issue{currency, ammAccount});
@@ -632,7 +633,7 @@ ammAccountHolds(ReadView const& view, AccountID const& ammAccountID, Asset const
// Get the actual AMM balance without factoring in the balance hook
return asset.visit(
[&](MPTIssue const& issue) {
if (auto const sle = view.read(keylet::mptoken(issue, ammAccountID));
if (MPTokenEntry<ReadView> const sle{keylet::mptoken(issue, ammAccountID), view};
sle && !isFrozen(view, ammAccountID, issue))
return STAmount{issue, (*sle)[sfMPTAmount]};
return STAmount{asset};
@@ -640,12 +641,12 @@ ammAccountHolds(ReadView const& view, AccountID const& ammAccountID, Asset const
[&](Issue const& issue) {
if (isXRP(issue))
{
if (auto const sle = view.read(keylet::account(ammAccountID)))
if (AccountRootEntry<ReadView> const sle{keylet::account(ammAccountID), view})
return (*sle)[sfBalance];
}
else if (
auto const sle =
view.read(keylet::trustLine(ammAccountID, issue.account, issue.currency));
RippleStateEntry<ReadView> const sle{
keylet::trustLine(ammAccountID, issue.account, issue.currency), view};
sle && !isFrozen(view, ammAccountID, issue.currency, issue.account))
{
STAmount amount = (*sle)[sfBalance];
@@ -746,7 +747,7 @@ deleteAMMMPTokens(Sandbox& sb, AccountID const& ammAccountID, beast::Journal j)
TER
deleteAMMAccount(Sandbox& sb, Asset const& asset, Asset const& asset2, beast::Journal j)
{
auto ammSle = sb.peek(keylet::amm(asset, asset2));
AMMEntry<ApplyView> ammSle{keylet::amm(asset, asset2), sb};
if (!ammSle)
{
// LCOV_EXCL_START
@@ -756,7 +757,7 @@ deleteAMMAccount(Sandbox& sb, Asset const& asset, Asset const& asset2, beast::Jo
}
auto const ammAccountID = (*ammSle)[sfAccount];
auto sleAMMRoot = sb.peek(keylet::account(ammAccountID));
AccountRootEntry<ApplyView> sleAMMRoot{keylet::account(ammAccountID), sb};
if (!sleAMMRoot)
{
// LCOV_EXCL_START
@@ -793,8 +794,8 @@ deleteAMMAccount(Sandbox& sb, Asset const& asset, Asset const& asset2, beast::Jo
// LCOV_EXCL_STOP
}
sb.erase(ammSle);
sb.erase(sleAMMRoot);
ammSle.erase();
sleAMMRoot.erase();
return tesSUCCESS;
}
@@ -885,12 +886,12 @@ isOnlyLiquidityProvider(ReadView const& view, Issue const& ammIssue, AccountID c
// Iterate over AMM owner directory objects.
while (limit-- >= 1)
{
auto const ownerDir = view.read(currentIndex);
DirectoryNodeEntry<ReadView> const ownerDir{currentIndex, view};
if (!ownerDir)
return std::unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
for (auto const& key : ownerDir->getFieldV256(sfIndexes))
{
auto const sle = view.read(keylet::child(key));
ReadOnlySLE const sle{keylet::child(key), view};
if (!sle)
return std::unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
auto const entryType = sle->getFieldU16(sfLedgerEntryType);

View File

@@ -8,6 +8,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -36,7 +37,7 @@ isGlobalFrozen(ReadView const& view, AccountID const& issuer)
{
if (isXRP(issuer))
return false;
if (auto const sle = view.read(keylet::account(issuer)))
if (AccountRootEntry<ReadView> sle{keylet::account(issuer), view})
return sle->isFlag(lsfGlobalFreeze);
return false;
}
@@ -86,8 +87,8 @@ confineOwnerCount(
XRPAmount
xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j)
{
auto const sle = view.read(keylet::account(id));
if (sle == nullptr)
AccountRootEntry<ReadView> sle{keylet::account(id), view};
if (!sle)
return beast::kZero;
// Return balance minus reserve
@@ -96,7 +97,7 @@ xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj,
// Pseudo-accounts have no reserve requirement
auto const reserve =
isPseudoAccount(sle) ? XRPAmount{0} : view.fees().accountReserve(ownerCount);
isPseudoAccount(sle.sle()) ? XRPAmount{0} : view.fees().accountReserve(ownerCount);
auto const fullBalance = sle->getFieldAmount(sfBalance);
@@ -116,7 +117,7 @@ xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj,
Rate
transferRate(ReadView const& view, AccountID const& issuer)
{
auto const sle = view.read(keylet::account(issuer));
AccountRootEntry<ReadView> sle{keylet::account(issuer), view};
if (sle && sle->isFieldPresent(sfTransferRate))
return Rate{sle->getFieldU32(sfTransferRate)};

View File

@@ -8,6 +8,7 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -53,13 +54,13 @@ removeExpired(ApplyView& view, STVector256 const& arr, beast::Journal const j)
{
// Credentials already checked in preclaim. Look only for expired here.
auto const k = keylet::credential(h);
auto const sleCred = view.peek(k);
CredentialEntry<ApplyView> sleCred{k, view};
if (sleCred && checkExpired(*sleCred, closeTime))
{
JLOG(j.trace()) << "Credentials are expired. Cred: " << sleCred->getText();
// delete expired credentials even if the transaction failed
auto const err = deleteSLE(view, sleCred, j);
auto const err = deleteSLE(view, sleCred.mutableSle(), j);
if (view.rules().enabled(fixCleanup3_1_3) && !isTesSuccess(err))
return std::unexpected(err);
foundExpired = true;
@@ -77,7 +78,7 @@ deleteSLE(ApplyView& view, SLE::ref sleCredential, beast::Journal j)
auto delSLE = [&view, &sleCredential, j](
AccountID const& account, SField const& node, bool isOwner) -> TER {
auto const sleAccount = view.peek(keylet::account(account));
AccountRootEntry<ApplyView> sleAccount{keylet::account(account), view};
if (!sleAccount)
{
// LCOV_EXCL_START
@@ -97,7 +98,7 @@ deleteSLE(ApplyView& view, SLE::ref sleCredential, beast::Journal j)
}
if (isOwner)
adjustOwnerCount(view, sleAccount, -1, j);
adjustOwnerCount(view, sleAccount.mutableSle(), -1, j);
return tesSUCCESS;
};
@@ -160,7 +161,7 @@ valid(STTx const& tx, ReadView const& view, AccountID const& src, beast::Journal
auto const& credIDs(tx.getFieldV256(sfCredentialIDs));
for (auto const& h : credIDs)
{
auto const sleCred = view.read(keylet::credential(h));
CredentialEntry<ReadView> sleCred{keylet::credential(h), view};
if (!sleCred)
{
JLOG(j.trace()) << "Credential doesn't exist. Cred: " << h;
@@ -189,7 +190,7 @@ TER
validDomain(ReadView const& view, uint256 domainID, AccountID const& subject)
{
// Note, permissioned domain objects can be deleted at any time
auto const slePD = view.read(keylet::permissionedDomain(domainID));
PermissionedDomainEntry<ReadView> slePD{keylet::permissionedDomain(domainID), view};
if (!slePD)
return tecOBJECT_NOT_FOUND;
@@ -200,7 +201,7 @@ validDomain(ReadView const& view, uint256 domainID, AccountID const& subject)
auto const issuer = h.getAccountID(sfIssuer);
auto const type = h.getFieldVL(sfCredentialType);
auto const keyletCredential = keylet::credential(subject, issuer, makeSlice(type));
auto const sleCredential = view.read(keyletCredential);
CredentialEntry<ReadView> sleCredential{keyletCredential, view};
// We cannot delete expired credentials, that would require ApplyView&
// However we can check if credentials are expired. Expected transaction
@@ -234,14 +235,14 @@ authorizedDepositPreauth(ReadView const& view, STVector256 const& credIDs, Accou
lifeExtender.reserve(credIDs.size());
for (auto const& h : credIDs)
{
auto sleCred = view.read(keylet::credential(h));
CredentialEntry<ReadView> sleCred{keylet::credential(h), view};
if (!sleCred) // already checked in preclaim
return tefINTERNAL; // LCOV_EXCL_LINE
auto [it, ins] = sorted.emplace((*sleCred)[sfIssuer], (*sleCred)[sfCredentialType]);
if (!ins)
return tefINTERNAL; // LCOV_EXCL_LINE
lifeExtender.push_back(std::move(sleCred));
lifeExtender.push_back(sleCred.sle());
}
if (!view.exists(keylet::depositPreauth(dst, sorted)))
@@ -312,7 +313,7 @@ checkArray(STArray const& credentials, unsigned maxSize, beast::Journal j)
TER
verifyValidDomain(ApplyView& view, AccountID const& account, uint256 domainID, beast::Journal j)
{
auto const slePD = view.read(keylet::permissionedDomain(domainID));
PermissionedDomainEntry<ReadView> slePD{keylet::permissionedDomain(domainID), view};
if (!slePD)
return tecOBJECT_NOT_FOUND;
@@ -334,7 +335,7 @@ verifyValidDomain(ApplyView& view, AccountID const& account, uint256 domainID, b
for (auto const& h : credentials)
{
auto sleCredential = view.read(keylet::credential(h));
CredentialEntry<ReadView> sleCredential{keylet::credential(h), view};
if (!sleCredential)
continue; // expired, i.e. deleted in credentials::removeExpired

View File

@@ -11,6 +11,7 @@
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
@@ -40,7 +41,8 @@ namespace xrpl {
bool
isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue)
{
if (auto const sle = view.read(keylet::mptokenIssuance(mptIssue.getMptID())))
if (MPTokenIssuanceEntry<ReadView> const sle{
keylet::mptokenIssuance(mptIssue.getMptID()), view})
return sle->isFlag(lsfMPTLocked);
return false;
}
@@ -48,7 +50,7 @@ isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue)
bool
isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue)
{
if (auto const sle = view.read(keylet::mptoken(mptIssue.getMptID(), account)))
if (MPTokenEntry<ReadView> const sle{keylet::mptoken(mptIssue.getMptID(), account), view})
return sle->isFlag(lsfMPTLocked);
return false;
}
@@ -95,7 +97,7 @@ transferRate(ReadView const& view, MPTID const& issuanceID)
// fee is 0-50,000 (0-50%), rate is 1,000,000,000-2,000,000,000
// For example, if transfer fee is 50% then 10,000 * 50,000 = 500,000
// which represents 50% of 1,000,000,000
if (auto const sle = view.read(keylet::mptokenIssuance(issuanceID));
if (MPTokenIssuanceEntry<ReadView> const sle{keylet::mptokenIssuance(issuanceID), view};
sle && sle->isFieldPresent(sfTransferFee))
{
auto const fee = sle->getFieldU16(sfTransferFee);
@@ -110,7 +112,7 @@ transferRate(ReadView const& view, MPTID const& issuanceID)
canAddHolding(ReadView const& view, MPTIssue const& mptIssue)
{
auto mptID = mptIssue.getMptID();
auto issuance = view.read(keylet::mptokenIssuance(mptID));
MPTokenIssuanceEntry<ReadView> const issuance{keylet::mptokenIssuance(mptID), view};
if (!issuance)
{
return tecOBJECT_NOT_FOUND;
@@ -132,7 +134,7 @@ addEmptyHolding(
beast::Journal journal)
{
auto const& mptID = mptIssue.getMptID();
auto const mpt = view.peek(keylet::mptokenIssuance(mptID));
MPTokenIssuanceEntry<ApplyView> const mpt{keylet::mptokenIssuance(mptID), view};
if (!mpt)
return tefINTERNAL; // LCOV_EXCL_LINE
if (mpt->isFlag(lsfMPTLocked))
@@ -155,7 +157,7 @@ authorizeMPToken(
std::uint32_t flags,
std::optional<AccountID> holderID)
{
auto const sleAcct = view.peek(keylet::account(account));
AccountRootEntry<ApplyView> const sleAcct{keylet::account(account), view};
if (!sleAcct)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -170,7 +172,7 @@ authorizeMPToken(
if ((flags & tfMPTUnauthorize) != 0u)
{
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
auto const sleMpt = view.peek(mptokenKey);
MPTokenEntry<ApplyView> sleMpt{mptokenKey, view};
if (!sleMpt || (*sleMpt)[sfMPTAmount] != 0 ||
(view.rules().enabled(fixCleanup3_1_3) &&
(*sleMpt)[~sfLockedAmount].valueOr(0) != 0))
@@ -180,9 +182,9 @@ authorizeMPToken(
keylet::ownerDir(account), (*sleMpt)[sfOwnerNode], sleMpt->key(), false))
return tecINTERNAL; // LCOV_EXCL_LINE
adjustOwnerCount(view, sleAcct, -1, journal);
adjustOwnerCount(view, sleAcct.mutableSle(), -1, journal);
view.erase(sleMpt);
sleMpt.erase();
return tesSUCCESS;
}
@@ -204,7 +206,7 @@ authorizeMPToken(
return tecINSUFFICIENT_RESERVE;
// Defensive check before we attempt to create MPToken for the issuer
auto const mpt = view.read(keylet::mptokenIssuance(mptIssuanceID));
MPTokenIssuanceEntry<ReadView> const mpt{keylet::mptokenIssuance(mptIssuanceID), view};
if (!mpt || mpt->getAccountID(sfIssuer) == account)
{
// LCOV_EXCL_START
@@ -225,12 +227,13 @@ authorizeMPToken(
view.insert(mptoken);
// Update owner count.
adjustOwnerCount(view, sleAcct, 1, journal);
adjustOwnerCount(view, sleAcct.mutableSle(), 1, journal);
return tesSUCCESS;
}
auto const sleMptIssuance = view.read(keylet::mptokenIssuance(mptIssuanceID));
MPTokenIssuanceEntry<ReadView> const sleMptIssuance{
keylet::mptokenIssuance(mptIssuanceID), view};
if (!sleMptIssuance)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -240,7 +243,7 @@ authorizeMPToken(
if (account != (*sleMptIssuance)[sfIssuer])
return tecINTERNAL; // LCOV_EXCL_LINE
auto const sleMpt = view.peek(keylet::mptoken(mptIssuanceID, *holderID));
MPTokenEntry<ApplyView> sleMpt{keylet::mptoken(mptIssuanceID, *holderID), view};
if (!sleMpt)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -263,7 +266,7 @@ authorizeMPToken(
if (flagsIn != flagsOut)
sleMpt->setFieldU32(sfFlags, flagsOut);
view.update(sleMpt);
sleMpt.update();
return tesSUCCESS;
}
@@ -279,7 +282,7 @@ removeEmptyHolding(
// a token does exist, it will get deleted. If not, return success.
bool const accountIsIssuer = accountID == mptIssue.getIssuer();
auto const& mptID = mptIssue.getMptID();
auto const mptoken = view.peek(keylet::mptoken(mptID, accountID));
MPTokenEntry<ApplyView> mptoken{keylet::mptoken(mptID, accountID), view};
if (!mptoken)
return accountIsIssuer ? (TER)tesSUCCESS : (TER)tecOBJECT_NOT_FOUND;
// Unlike a trust line, if the account is the issuer, and the token has a
@@ -330,7 +333,7 @@ requireAuth(
};
auto const mptID = keylet::mptokenIssuance(mptIssue.getMptID());
auto const sleIssuance = view.read(mptID);
MPTokenIssuanceEntry<ReadView> const sleIssuance{mptID, view};
if (!sleIssuance)
return tecOBJECT_NOT_FOUND;
@@ -355,13 +358,14 @@ requireAuth(
}
// requireAuth is recursive if the issuer is a vault pseudo-account
auto const sleIssuer = view.read(keylet::account(mptIssuer));
AccountRootEntry<ReadView> const sleIssuer{keylet::account(mptIssuer), view};
if (!sleIssuer)
return tefINTERNAL; // LCOV_EXCL_LINE
if (sleIssuer->isFieldPresent(sfVaultID))
{
auto const sleVault = view.read(keylet::vault(sleIssuer->getFieldH256(sfVaultID)));
VaultEntry<ReadView> const sleVault{
keylet::vault(sleIssuer->getFieldH256(sfVaultID)), view};
if (!sleVault)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -377,7 +381,7 @@ requireAuth(
}
auto const mptokenID = keylet::mptoken(mptID.key, account);
auto const sleToken = view.read(mptokenID);
MPTokenEntry<ReadView> const sleToken{mptokenID, view};
// if account has no MPToken, fail
if (!sleToken && (authType == AuthType::StrongAuth || authType == AuthType::Legacy))
@@ -425,7 +429,7 @@ enforceMPTokenAuthorization(
XRPAmount const& priorBalance, // for MPToken authorization
beast::Journal j)
{
auto const sleIssuance = view.read(keylet::mptokenIssuance(mptIssuanceID));
MPTokenIssuanceEntry<ReadView> const sleIssuance{keylet::mptokenIssuance(mptIssuanceID), view};
if (!sleIssuance)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -437,7 +441,7 @@ enforceMPTokenAuthorization(
return tefINTERNAL; // LCOV_EXCL_LINE
auto const keylet = keylet::mptoken(mptIssuanceID, account);
auto const sleToken = view.read(keylet); // NOTE: might be null
MPTokenEntry<ReadView> const sleToken{keylet, view}; // NOTE: might be null
auto const maybeDomainID = sleIssuance->at(~sfDomainID);
bool expired = false;
bool const authorizedByDomain = [&]() -> bool {
@@ -453,7 +457,7 @@ enforceMPTokenAuthorization(
return false;
}();
if (!authorizedByDomain && sleToken == nullptr)
if (!authorizedByDomain && !sleToken)
{
// Could not find MPToken and won't create one, could be either of:
//
@@ -476,14 +480,14 @@ enforceMPTokenAuthorization(
// We found an MPToken, but sfDomainID is not set, so this is a classic
// MPToken which requires authorization by the token issuer.
XRPL_ASSERT(
sleToken != nullptr && !maybeDomainID.has_value(),
sleToken && !maybeDomainID.has_value(),
"xrpl::enforceMPTokenAuthorization : found MPToken");
if (sleToken->isFlag(lsfMPTAuthorized))
return tesSUCCESS;
return tecNO_AUTH;
}
if (authorizedByDomain && sleToken != nullptr)
if (authorizedByDomain && sleToken)
{
// Found an MPToken, authorized by the domain. Ignore authorization flag
// lsfMPTAuthorized because it is meaningless. Return tesSUCCESS
@@ -497,7 +501,7 @@ enforceMPTokenAuthorization(
// Could not find MPToken but there should be one because we are
// authorized by domain. Proceed to create it, then return tesSUCCESS
XRPL_ASSERT(
maybeDomainID.has_value() && sleToken == nullptr,
maybeDomainID.has_value() && !sleToken,
"xrpl::enforceMPTokenAuthorization : new MPToken for domain");
if (auto const err = authorizeMPToken(
view,
@@ -550,7 +554,7 @@ canTransfer(
std::uint8_t depth)
{
auto const mptID = keylet::mptokenIssuance(mptIssue.getMptID());
auto const sleIssuance = view.read(mptID);
MPTokenIssuanceEntry<ReadView> const sleIssuance{mptID, view};
if (!sleIssuance)
return tecOBJECT_NOT_FOUND;
@@ -580,8 +584,8 @@ canTransfer(
// LCOV_EXCL_STOP
}
auto const sleHolding =
view.read(keylet::unchecked(sleIssuance->getFieldH256(sfReferenceHolding)));
ReadOnlySLE const sleHolding{
keylet::unchecked(sleIssuance->getFieldH256(sfReferenceHolding)), view};
if (!sleHolding)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -603,7 +607,8 @@ canTrade(ReadView const& view, Asset const& asset, std::uint8_t depth)
return asset.visit(
[&](Issue const&) -> TER { return tesSUCCESS; },
[&](MPTIssue const& mptIssue) -> TER {
auto const sleIssuance = view.read(keylet::mptokenIssuance(mptIssue.getMptID()));
MPTokenIssuanceEntry<ReadView> const sleIssuance{
keylet::mptokenIssuance(mptIssue.getMptID()), view};
if (!sleIssuance)
return tecOBJECT_NOT_FOUND;
if (!sleIssuance->isFlag(lsfMPTCanTrade))
@@ -625,8 +630,8 @@ canTrade(ReadView const& view, Asset const& asset, std::uint8_t depth)
return tecINTERNAL;
// LCOV_EXCL_STOP
}
auto const sleHolding =
view.read(keylet::unchecked(sleIssuance->getFieldH256(sfReferenceHolding)));
ReadOnlySLE const sleHolding{
keylet::unchecked(sleIssuance->getFieldH256(sfReferenceHolding)), view};
if (!sleHolding)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -658,7 +663,7 @@ lockEscrowMPT(ApplyView& view, AccountID const& sender, STAmount const& amount,
{
auto const mptIssue = amount.get<MPTIssue>();
auto const mptID = keylet::mptokenIssuance(mptIssue.getMptID());
auto sleIssuance = view.peek(mptID);
MPTokenIssuanceEntry<ApplyView> sleIssuance{mptID, view};
if (!sleIssuance)
{ // LCOV_EXCL_START
JLOG(j.error()) << "lockEscrowMPT: MPT issuance not found for " << mptIssue.getMptID();
@@ -675,7 +680,7 @@ lockEscrowMPT(ApplyView& view, AccountID const& sender, STAmount const& amount,
// 2. Increase the MPT Holder EscrowedAmount
{
auto const mptokenID = keylet::mptoken(mptID.key, sender);
auto sle = view.peek(mptokenID);
MPTokenEntry<ApplyView> sle{mptokenID, view};
if (!sle)
{ // LCOV_EXCL_START
JLOG(j.error()) << "lockEscrowMPT: MPToken not found for " << sender;
@@ -714,7 +719,7 @@ lockEscrowMPT(ApplyView& view, AccountID const& sender, STAmount const& amount,
sle->setFieldU64(sfLockedAmount, pay);
}
view.update(sle);
sle.update();
}
// 1. Increase the Issuance EscrowedAmount
@@ -741,7 +746,7 @@ lockEscrowMPT(ApplyView& view, AccountID const& sender, STAmount const& amount,
sleIssuance->setFieldU64(sfLockedAmount, pay);
}
view.update(sleIssuance);
sleIssuance.update();
}
return tesSUCCESS;
}
@@ -763,7 +768,7 @@ unlockEscrowMPT(
auto const& issuer = netAmount.getIssuer();
auto const& mptIssue = netAmount.get<MPTIssue>();
auto const mptID = keylet::mptokenIssuance(mptIssue.getMptID());
auto sleIssuance = view.peek(mptID);
MPTokenIssuanceEntry<ApplyView> sleIssuance{mptID, view};
if (!sleIssuance)
{ // LCOV_EXCL_START
JLOG(j.error()) << "unlockEscrowMPT: MPT issuance not found for " << mptIssue.getMptID();
@@ -799,14 +804,14 @@ unlockEscrowMPT(
{
sleIssuance->setFieldU64(sfLockedAmount, newLocked);
}
view.update(sleIssuance);
sleIssuance.update();
}
if (issuer != receiver)
{
// Increase the MPT Holder MPTAmount
auto const mptokenID = keylet::mptoken(mptID.key, receiver);
auto sle = view.peek(mptokenID);
MPTokenEntry<ApplyView> sle{mptokenID, view};
if (!sle)
{ // LCOV_EXCL_START
JLOG(j.error()) << "unlockEscrowMPT: MPToken not found for " << receiver;
@@ -825,7 +830,7 @@ unlockEscrowMPT(
} // LCOV_EXCL_STOP
(*sle)[sfMPTAmount] += delta;
view.update(sle);
sle.update();
}
else
{
@@ -842,7 +847,7 @@ unlockEscrowMPT(
} // LCOV_EXCL_STOP
sleIssuance->setFieldU64(sfOutstandingAmount, outstanding - redeem);
view.update(sleIssuance);
sleIssuance.update();
}
if (issuer == sender)
@@ -853,7 +858,7 @@ unlockEscrowMPT(
} // LCOV_EXCL_STOP
// Decrease the MPT Holder EscrowedAmount
auto const mptokenID = keylet::mptoken(mptID.key, sender);
auto sle = view.peek(mptokenID);
MPTokenEntry<ApplyView> sle{mptokenID, view};
if (!sle)
{ // LCOV_EXCL_START
JLOG(j.error()) << "unlockEscrowMPT: MPToken not found for " << sender;
@@ -886,7 +891,7 @@ unlockEscrowMPT(
{
sle->setFieldU64(sfLockedAmount, newLocked);
}
view.update(sle);
sle.update();
// Note: The gross amount is the amount that was locked, the net
// amount is the amount that is being unlocked. The difference is the fee
@@ -905,7 +910,7 @@ unlockEscrowMPT(
} // LCOV_EXCL_STOP
sleIssuance->setFieldU64(sfOutstandingAmount, outstanding - diff);
view.update(sleIssuance);
sleIssuance.update();
}
return tesSUCCESS;
}
@@ -925,13 +930,14 @@ createMPToken(
if (!ownerNode)
return tecDIR_FULL; // LCOV_EXCL_LINE
auto mptoken = std::make_shared<SLE>(mptokenKey);
MPTokenEntry<ApplyView> mptoken{mptokenKey, view};
mptoken.newSLE();
(*mptoken)[sfAccount] = account;
(*mptoken)[sfMPTokenIssuanceID] = mptIssuanceID;
(*mptoken)[sfFlags] = flags;
(*mptoken)[sfOwnerNode] = *ownerNode;
view.insert(mptoken);
mptoken.insert();
return tesSUCCESS;
}
@@ -955,12 +961,12 @@ checkCreateMPT(
{
return err;
}
auto const sleAcct = view.peek(keylet::account(holder));
AccountRootEntry<ApplyView> const sleAcct{keylet::account(holder), view};
if (!sleAcct)
{
return tecINTERNAL;
}
adjustOwnerCount(view, sleAcct, 1, j);
adjustOwnerCount(view, sleAcct.mutableSle(), 1, j);
}
return tesSUCCESS;
}
@@ -982,7 +988,7 @@ availableMPTAmount(SLE const& sleIssuance)
std::int64_t
availableMPTAmount(ReadView const& view, MPTID const& mptID)
{
auto const sle = view.read(keylet::mptokenIssuance(mptID));
MPTokenIssuanceEntry<ReadView> const sle{keylet::mptokenIssuance(mptID), view};
if (!sle)
Throw<std::runtime_error>(transHuman(tecINTERNAL));
return availableMPTAmount(*sle);
@@ -1006,7 +1012,7 @@ issuerFundsToSelfIssue(ReadView const& view, MPTIssue const& issue)
{
STAmount amount{issue};
auto const sle = view.read(keylet::mptokenIssuance(issue));
MPTokenIssuanceEntry<ReadView> const sle{keylet::mptokenIssuance(issue), view};
if (!sle)
return amount;
auto const available = availableMPTAmount(*sle);

View File

@@ -10,6 +10,7 @@
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
@@ -182,7 +183,8 @@ getPageForToken(
? narr[kDirMaxTokensPerPage - 1].getFieldH256(sfNFTokenID).next()
: carr[0].getFieldH256(sfNFTokenID);
auto np = std::make_shared<SLE>(keylet::nftokenPage(base, tokenIDForNewPage));
NFTokenPageEntry<ApplyView> np{base, tokenIDForNewPage, view};
np.newSLE();
XRPL_ASSERT(np->key() > base.key, "xrpl::nft::getPageForToken : valid NFT page index");
np->setFieldArray(sfNFTokens, narr);
np->setFieldH256(sfNextPageMin, cp->key());
@@ -191,14 +193,14 @@ getPageForToken(
{
np->setFieldH256(sfPreviousPageMin, *ppm);
if (auto p3 = view.peek(Keylet(ltNFTOKEN_PAGE, *ppm)))
if (NFTokenPageEntry<ApplyView> p3{Keylet(ltNFTOKEN_PAGE, *ppm), view})
{
p3->setFieldH256(sfNextPageMin, np->key());
view.update(p3);
p3.update();
}
}
view.insert(np);
np.insert();
cp->setFieldArray(sfNFTokens, carr);
cp->setFieldH256(sfPreviousPageMin, np->key());
@@ -206,7 +208,7 @@ getPageForToken(
createCallback(view, owner);
return (first.key < np->key()) ? np : cp;
return (first.key < np->key()) ? np.mutableSle() : cp;
}
bool
@@ -230,7 +232,7 @@ changeTokenURI(
uint256 const& nftokenID,
std::optional<xrpl::Slice> const& uri)
{
SLE::pointer const page = locatePage(view, owner, nftokenID);
NFTokenPageEntry<ApplyView> page{locatePage(view, owner, nftokenID), view};
// If the page couldn't be found, the given NFT isn't owned by this account
if (!page)
@@ -254,7 +256,7 @@ changeTokenURI(
nftIter->makeFieldAbsent(sfURI);
}
view.update(page);
page.update();
return tesSUCCESS;
}
@@ -267,14 +269,19 @@ insertToken(ApplyView& view, AccountID owner, STObject&& nft)
// First, we need to locate the page the NFT belongs to, creating it
// if necessary. This operation may fail if it is impossible to insert
// the NFT.
SLE::pointer const page =
getPageForToken(view, owner, nft[sfNFTokenID], [](ApplyView& view, AccountID const& owner) {
adjustOwnerCount(
view,
view.peek(keylet::account(owner)),
1,
beast::Journal{beast::Journal::getNullSink()});
});
NFTokenPageEntry<ApplyView> page{
getPageForToken(
view,
owner,
nft[sfNFTokenID],
[](ApplyView& view, AccountID const& owner) {
adjustOwnerCount(
view,
view.peek(keylet::account(owner)),
1,
beast::Journal{beast::Journal::getNullSink()});
}),
view};
if (!page)
return tecNO_SUITABLE_NFTOKEN_PAGE;
@@ -290,7 +297,7 @@ insertToken(ApplyView& view, AccountID owner, STObject&& nft)
page->setFieldArray(sfNFTokens, arr);
}
view.update(page);
page.update();
return tesSUCCESS;
}
@@ -334,13 +341,13 @@ mergePages(ApplyView& view, SLE::ref p1, SLE::ref p2)
if (auto const ppm = (*p1)[~sfPreviousPageMin])
{
auto p0 = view.peek(Keylet(ltNFTOKEN_PAGE, *ppm));
NFTokenPageEntry<ApplyView> p0{Keylet(ltNFTOKEN_PAGE, *ppm), view};
if (!p0)
Throw<std::runtime_error>("mergePages: p0 can't be located!");
p0->setFieldH256(sfNextPageMin, p2->key());
view.update(p0);
p0.update();
p2->setFieldH256(sfPreviousPageMin, *ppm);
}
@@ -355,13 +362,13 @@ mergePages(ApplyView& view, SLE::ref p1, SLE::ref p2)
TER
removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID)
{
SLE::pointer const page = locatePage(view, owner, nftokenID);
NFTokenPageEntry<ApplyView> page{locatePage(view, owner, nftokenID), view};
// If the page couldn't be found, the given NFT isn't owned by this account
if (!page)
return tecNO_ENTRY;
return removeToken(view, owner, nftokenID, page);
return removeToken(view, owner, nftokenID, page.mutableSle());
}
/** Remove the token from the owner's token directory. */
@@ -400,8 +407,8 @@ removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID, S
return page2;
};
auto const prev = loadPage(curr, sfPreviousPageMin);
auto const next = loadPage(curr, sfNextPageMin);
NFTokenPageEntry<ApplyView> prev{loadPage(curr, sfPreviousPageMin), view};
NFTokenPageEntry<ApplyView> next{loadPage(curr, sfNextPageMin), view};
if (!arr.empty())
{
@@ -413,10 +420,10 @@ removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID, S
int cnt = 0;
if (prev && mergePages(view, prev, curr))
if (prev && mergePages(view, prev.mutableSle(), curr))
cnt--;
if (next && mergePages(view, curr, next))
if (next && mergePages(view, curr, next.mutableSle()))
cnt--;
if (cnt != 0)
@@ -451,9 +458,9 @@ removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID, S
curr->at(sfPreviousPageMin) = *prevLink;
// Also fix up the NextPageMin link in the new Previous.
auto const newPrev = loadPage(curr, sfPreviousPageMin);
NFTokenPageEntry<ApplyView> newPrev{loadPage(curr, sfPreviousPageMin), view};
newPrev->at(sfNextPageMin) = curr->key();
view.update(newPrev);
newPrev.update();
}
else
{
@@ -467,7 +474,7 @@ removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID, S
beast::Journal{beast::Journal::getNullSink()});
view.update(curr);
view.erase(prev);
prev.erase();
return tesSUCCESS;
}
@@ -482,7 +489,7 @@ removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID, S
prev->makeFieldAbsent(sfNextPageMin);
}
view.update(prev);
prev.update();
}
if (next)
@@ -497,7 +504,7 @@ removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID, S
next->makeFieldAbsent(sfPreviousPageMin);
}
view.update(next);
next.update();
}
view.erase(curr);
@@ -531,7 +538,7 @@ removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID, S
std::optional<STObject>
findToken(ReadView const& view, AccountID const& owner, uint256 const& nftokenID)
{
SLE::const_pointer const page = locatePage(view, owner, nftokenID);
NFTokenPageEntry<ReadView> const page{locatePage(view, owner, nftokenID), view};
// If the page couldn't be found, the given NFT isn't owned by this account
if (!page)
@@ -579,7 +586,7 @@ removeTokenOffersWithLimit(ApplyView& view, Keylet const& directory, std::size_t
do
{
auto const page = view.peek(keylet::page(directory, *pageIndex));
DirectoryNodeEntry<ApplyView> const page{keylet::page(directory, *pageIndex), view};
if (!page)
break;
@@ -597,9 +604,10 @@ removeTokenOffersWithLimit(ApplyView& view, Keylet const& directory, std::size_t
// deleting during iteration.
for (int i = offerIndexes.size() - 1; i >= 0; --i)
{
if (auto const offer = view.peek(keylet::nftokenOffer(offerIndexes[i])))
if (NFTokenOfferEntry<ApplyView> const offer{
keylet::nftokenOffer(offerIndexes[i]), view})
{
if (deleteTokenOffer(view, offer))
if (deleteTokenOffer(view, offer.mutableSle()))
{
++deletedOffersCount;
}
@@ -740,7 +748,7 @@ repairNFTokenDirectoryLinks(ApplyView& view, AccountID const& owner)
nextPage->at(sfPreviousPageMin) = *prevLink;
// Also fix up the NextPageMin link in the new Previous.
auto const newPrev = view.peek(Keylet(ltNFTOKEN_PAGE, *prevLink));
NFTokenPageEntry<ApplyView> newPrev{Keylet(ltNFTOKEN_PAGE, *prevLink), view};
if (!newPrev)
{
Throw<std::runtime_error>(
@@ -748,7 +756,7 @@ repairNFTokenDirectoryLinks(ApplyView& view, AccountID const& owner)
" cannot be repaired. Unexpected link problem.");
}
newPrev->at(sfNextPageMin) = nextPage->key();
view.update(newPrev);
newPrev.update();
}
view.erase(page);
view.insert(nextPage);
@@ -853,7 +861,7 @@ tokenOfferCreatePreclaim(
if (nftIssuer != acctID && ((nftFlags & nft::kFlagTransferable) == 0))
{
auto const root = view.read(keylet::account(nftIssuer));
AccountRootEntry<ReadView> const root{keylet::account(nftIssuer), view};
XRPL_ASSERT(root, "xrpl::nft::tokenOfferCreatePreclaim : non-null account");
if (auto minter = (*root)[~sfNFTokenMinter]; minter != acctID)
@@ -878,7 +886,7 @@ tokenOfferCreatePreclaim(
{
// If a destination is specified, the destination must already be in
// the ledger.
auto const sleDst = view.read(keylet::account(*dest));
AccountRootEntry<ReadView> const sleDst{keylet::account(*dest), view};
if (!sleDst)
return tecNO_DST;
@@ -890,7 +898,7 @@ tokenOfferCreatePreclaim(
if (owner)
{
auto const sleOwner = view.read(keylet::account(*owner));
AccountRootEntry<ReadView> const sleOwner{keylet::account(*owner), view};
// defensively check
// it should not be possible to specify owner that doesn't exist
@@ -930,7 +938,7 @@ tokenOfferCreateApply(
std::uint32_t txFlags)
{
Keylet const acctKeylet = keylet::account(acctID);
if (auto const acct = view.read(acctKeylet);
if (AccountRootEntry<ReadView> const acct{acctKeylet, view};
priorBalance < view.fees().accountReserve((*acct)[sfOwnerCount] + 1))
return tecINSUFFICIENT_RESERVE;
@@ -965,7 +973,8 @@ tokenOfferCreateApply(
if (isSellOffer)
sleFlags |= lsfSellNFToken;
auto offer = std::make_shared<SLE>(offerID);
NFTokenOfferEntry<ApplyView> offer{offerID, view};
offer.newSLE();
(*offer)[sfOwner] = acctID;
(*offer)[sfNFTokenID] = nftokenID;
(*offer)[sfAmount] = amount;
@@ -979,7 +988,7 @@ tokenOfferCreateApply(
if (dest)
(*offer)[sfDestination] = *dest;
view.insert(offer);
offer.insert();
}
// Update owner count.
@@ -1000,7 +1009,7 @@ checkTrustlineAuthorized(
if (view.rules().enabled(fixEnforceNFTokenTrustlineV2))
{
auto const issuerAccount = view.read(keylet::account(issue.account));
AccountRootEntry<ReadView> const issuerAccount{keylet::account(issue.account), view};
if (!issuerAccount)
{
JLOG(j.debug()) << "xrpl::nft::checkTrustlineAuthorized: can't "
@@ -1020,7 +1029,7 @@ checkTrustlineAuthorized(
if (issuerAccount->isFlag(lsfRequireAuth))
{
auto const trustLine = view.read(keylet::trustLine(id, issue.account, issue.currency));
RippleStateEntry<ReadView> const trustLine{id, issue.account, issue.currency, view};
if (!trustLine)
{
@@ -1052,7 +1061,7 @@ checkTrustlineDeepFrozen(
if (view.rules().enabled(featureDeepFreeze))
{
auto const issuerAccount = view.read(keylet::account(issue.account));
AccountRootEntry<ReadView> const issuerAccount{keylet::account(issue.account), view};
if (!issuerAccount)
{
JLOG(j.debug()) << "xrpl::nft::checkTrustlineDeepFrozen: can't "
@@ -1070,7 +1079,7 @@ checkTrustlineDeepFrozen(
return tesSUCCESS;
}
auto const trustLine = view.read(keylet::trustLine(id, issue.account, issue.currency));
RippleStateEntry<ReadView> const trustLine{id, issue.account, issue.currency, view};
if (!trustLine)
{

View File

@@ -22,7 +22,11 @@
namespace xrpl {
TER
closeChannel(SLE::ref slep, ApplyView& view, uint256 const& key, beast::Journal j)
closeChannel(
PayChannelEntry<ApplyView>& slep,
ApplyView& view,
uint256 const& key,
beast::Journal j)
{
AccountID const src = (*slep)[sfAccount];
// Remove PayChan from owner directory
@@ -51,18 +55,18 @@ closeChannel(SLE::ref slep, ApplyView& view, uint256 const& key, beast::Journal
}
// Transfer amount back to owner, decrement owner count
auto const sle = view.peek(keylet::account(src));
AccountRootEntry<ApplyView> sle{src, view};
if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE
XRPL_ASSERT(
(*slep)[sfAmount] >= (*slep)[sfBalance], "xrpl::closeChannel : minimum channel amount");
(*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount] - (*slep)[sfBalance];
adjustOwnerCount(view, sle, -1, j);
view.update(sle);
adjustOwnerCount(view, sle.mutableSle(), -1, j);
sle.update();
// Remove PayChan from ledger
view.erase(slep);
slep.erase();
return tesSUCCESS;
}

View File

@@ -7,6 +7,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -31,7 +32,7 @@ accountInDomain(ReadView const& view, AccountID const& account, Domain const& do
// LCOV_EXCL_STOP
}
auto const sleDomain = view.read(keylet::permissionedDomain(domainID));
PermissionedDomainEntry<ReadView> sleDomain{keylet::permissionedDomain(domainID), view};
if (!sleDomain)
return false;
@@ -42,8 +43,8 @@ accountInDomain(ReadView const& view, AccountID const& account, Domain const& do
auto const& credentials = sleDomain->getFieldArray(sfAcceptedCredentials);
bool const inDomain = std::ranges::any_of(credentials, [&](auto const& credential) {
auto const sleCred = view.read(
keylet::credential(account, credential[sfIssuer], credential[sfCredentialType]));
CredentialEntry<ReadView> sleCred{
keylet::credential(account, credential[sfIssuer], credential[sfCredentialType]), view};
if (!sleCred || !sleCred->isFlag(lsfAccepted))
return false;
@@ -60,7 +61,7 @@ offerInDomain(
Domain const& domainID,
beast::Journal j)
{
auto const sleOffer = view.read(keylet::offer(offerID));
OfferEntry<ReadView> sleOffer{keylet::offer(offerID), view};
// The following are defensive checks that should never happen, since this
// function is used to check against the order book offers, which should not

View File

@@ -9,6 +9,7 @@
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/AmountConversions.h>
@@ -47,7 +48,7 @@ creditLimit(
{
STAmount result(Issue{currency, account});
auto sleRippleState = view.read(keylet::trustLine(account, issuer, currency));
RippleStateEntry<ReadView> sleRippleState{keylet::trustLine(account, issuer, currency), view};
if (sleRippleState)
{
@@ -78,7 +79,7 @@ creditBalance(
{
STAmount result(Issue{currency, account});
auto sleRippleState = view.read(keylet::trustLine(account, issuer, currency));
RippleStateEntry<ReadView> sleRippleState{keylet::trustLine(account, issuer, currency), view};
if (sleRippleState)
{
@@ -114,7 +115,7 @@ isIndividualFrozen(
if (issuer != account)
{
// Check if the issuer froze the line
auto const sle = view.read(keylet::trustLine(account, issuer, currency));
RippleStateEntry<ReadView> const sle{keylet::trustLine(account, issuer, currency), view};
if (sle && sle->isFlag((issuer > account) ? lsfHighFreeze : lsfLowFreeze))
return true;
}
@@ -162,7 +163,7 @@ isDeepFrozen(
return false;
}
auto const sle = view.read(keylet::trustLine(account, issuer, currency));
RippleStateEntry<ReadView> const sle{keylet::trustLine(account, issuer, currency), view};
if (!sle)
{
return false;
@@ -211,8 +212,9 @@ trustCreate(
// LCOV_EXCL_STOP
}
auto const sleRippleState = std::make_shared<SLE>(ltRIPPLE_STATE, uIndex);
view.insert(sleRippleState);
RippleStateEntry<ApplyView> sleRippleState{Keylet(ltRIPPLE_STATE, uIndex), view};
sleRippleState.newSLE();
sleRippleState.insert();
auto lowNode = view.dirInsert(
keylet::ownerDir(uLowAccountID), sleRippleState->key(), describeOwnerDir(uLowAccountID));
@@ -236,7 +238,8 @@ trustCreate(
XRPL_ASSERT(
sleAccount->getAccountID(sfAccount) == (bSetHigh ? uHighAccountID : uLowAccountID),
"xrpl::trustCreate : matching account ID");
auto const slePeer = view.peek(keylet::account(bSetHigh ? uLowAccountID : uHighAccountID));
AccountRootEntry<ApplyView> const slePeer{
keylet::account(bSetHigh ? uLowAccountID : uHighAccountID), view};
if (!slePeer)
return tecNO_TARGET;
@@ -342,7 +345,7 @@ updateTrustLine(
if (!state)
return false;
auto sle = view.peek(keylet::account(sender));
AccountRootEntry<ApplyView> sle{keylet::account(sender), view};
if (!sle)
return false;
@@ -369,7 +372,7 @@ updateTrustLine(
{
// VFALCO Where is the line being deleted?
// Clear the reserve of the sender, possibly delete the line!
adjustOwnerCount(view, sle, -1, j);
adjustOwnerCount(view, sle.mutableSle(), -1, j);
// Clear reserve flag.
state->clearFlag(senderReserveFlag);
@@ -405,7 +408,7 @@ issueIOU(
auto const index = keylet::trustLine(issue.account, account, issue.currency);
if (auto state = view.peek(index))
if (RippleStateEntry<ApplyView> state{index, view})
{
STAmount finalBalance = state->getFieldAmount(sfBalance);
@@ -416,8 +419,8 @@ issueIOU(
finalBalance -= amount;
auto const mustDelete =
updateTrustLine(view, state, bSenderHigh, issue.account, startBalance, finalBalance, j);
auto const mustDelete = updateTrustLine(
view, state.mutableSle(), bSenderHigh, issue.account, startBalance, finalBalance, j);
view.creditHookIOU(issue.account, account, amount, startBalance);
@@ -432,13 +435,13 @@ issueIOU(
{
return trustDelete(
view,
state,
state.mutableSle(),
bSenderHigh ? account : issue.account,
bSenderHigh ? issue.account : account,
j);
}
view.update(state);
state.update();
return tesSUCCESS;
}
@@ -451,7 +454,7 @@ issueIOU(
finalBalance.get<Issue>().account = noAccount();
auto const receiverAccount = view.peek(keylet::account(account));
AccountRootEntry<ApplyView> const receiverAccount{keylet::account(account), view};
if (!receiverAccount)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -463,7 +466,7 @@ issueIOU(
issue.account,
account,
index.key,
receiverAccount,
receiverAccount.mutableSle(),
false,
noRipple,
false,
@@ -497,7 +500,8 @@ redeemIOU(
bool const bSenderHigh = account > issue.account;
if (auto state = view.peek(keylet::trustLine(account, issue.account, issue.currency)))
if (RippleStateEntry<ApplyView> state{
keylet::trustLine(account, issue.account, issue.currency), view})
{
STAmount finalBalance = state->getFieldAmount(sfBalance);
@@ -508,8 +512,8 @@ redeemIOU(
finalBalance -= amount;
auto const mustDelete =
updateTrustLine(view, state, bSenderHigh, account, startBalance, finalBalance, j);
auto const mustDelete = updateTrustLine(
view, state.mutableSle(), bSenderHigh, account, startBalance, finalBalance, j);
view.creditHookIOU(account, issue.account, amount, startBalance);
@@ -525,13 +529,13 @@ redeemIOU(
{
return trustDelete(
view,
state,
state.mutableSle(),
bSenderHigh ? issue.account : account,
bSenderHigh ? account : issue.account,
j);
}
view.update(state);
state.update();
return tesSUCCESS;
}
@@ -558,14 +562,15 @@ 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));
RippleStateEntry<ReadView> const trustLine{
keylet::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;
// If this is a weak or legacy check, or if the account has a line, fail if
// auth is required and not set on the line
if (auto const issuerAccount = view.read(keylet::account(issue.account));
if (AccountRootEntry<ReadView> const issuerAccount{keylet::account(issue.account), view};
issuerAccount && issuerAccount->isFlag(lsfRequireAuth))
{
if (trustLine)
@@ -589,14 +594,14 @@ canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, Acc
auto const& issuerId = issue.getIssuer();
if (issuerId == from || issuerId == to)
return tesSUCCESS;
auto const sleIssuer = view.read(keylet::account(issuerId));
if (sleIssuer == nullptr)
AccountRootEntry<ReadView> const sleIssuer{keylet::account(issuerId), view};
if (!sleIssuer)
return tefINTERNAL; // LCOV_EXCL_LINE
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));
RippleStateEntry<ReadView> const line{keylet::trustLine(account, issue), view};
if (line)
{
bool const issuerHigh = issuerId > account;
@@ -639,8 +644,8 @@ addEmptyHolding(
auto const& dstId = accountID;
auto const high = srcId > dstId;
auto const index = keylet::trustLine(srcId, dstId, currency);
auto const sleSrc = view.peek(keylet::account(srcId));
auto const sleDst = view.peek(keylet::account(dstId));
AccountRootEntry<ApplyView> const sleSrc{keylet::account(srcId), view};
AccountRootEntry<ApplyView> const sleDst{keylet::account(dstId), view};
if (!sleDst || !sleSrc)
return tefINTERNAL; // LCOV_EXCL_LINE
if (!sleSrc->isFlag(lsfDefaultRipple))
@@ -660,7 +665,7 @@ addEmptyHolding(
srcId,
dstId,
index.key,
sleDst,
sleDst.mutableSle(),
/*bAuth=*/false,
/*bNoRipple=*/true,
/*bFreeze=*/false,
@@ -681,7 +686,7 @@ removeEmptyHolding(
{
if (issue.native())
{
auto const sle = view.read(keylet::account(accountID));
AccountRootEntry<ReadView> const sle{keylet::account(accountID), view};
if (!sle)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -696,7 +701,7 @@ 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 = view.peek(keylet::trustLine(accountID, issue));
RippleStateEntry<ApplyView> line{keylet::trustLine(accountID, issue), view};
if (!line)
return accountIsIssuer ? (TER)tesSUCCESS : (TER)tecOBJECT_NOT_FOUND;
if (!accountIsIssuer && line->at(sfBalance)->iou() != beast::kZero)
@@ -706,11 +711,12 @@ removeEmptyHolding(
if (line->isFlag(lsfLowReserve))
{
// Clear reserve for low account.
auto sleLowAccount = view.peek(keylet::account(line->at(sfLowLimit)->getIssuer()));
AccountRootEntry<ApplyView> sleLowAccount{
keylet::account(line->at(sfLowLimit)->getIssuer()), view};
if (!sleLowAccount)
return tecINTERNAL; // LCOV_EXCL_LINE
adjustOwnerCount(view, sleLowAccount, -1, journal);
adjustOwnerCount(view, sleLowAccount.mutableSle(), -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.
@@ -720,11 +726,12 @@ removeEmptyHolding(
if (line->isFlag(lsfHighReserve))
{
// Clear reserve for high account.
auto sleHighAccount = view.peek(keylet::account(line->at(sfHighLimit)->getIssuer()));
AccountRootEntry<ApplyView> sleHighAccount{
keylet::account(line->at(sfHighLimit)->getIssuer()), view};
if (!sleHighAccount)
return tecINTERNAL; // LCOV_EXCL_LINE
adjustOwnerCount(view, sleHighAccount, -1, journal);
adjustOwnerCount(view, sleHighAccount.mutableSle(), -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.
@@ -732,7 +739,11 @@ removeEmptyHolding(
}
return trustDelete(
view, line, line->at(sfLowLimit)->getIssuer(), line->at(sfHighLimit)->getIssuer(), journal);
view,
line.mutableSle(),
line->at(sfLowLimit)->getIssuer(),
line->at(sfHighLimit)->getIssuer(),
journal);
}
TER
@@ -748,8 +759,8 @@ deleteAMMTrustLine(
auto const& [low, high] = std::minmax(
sleState->getFieldAmount(sfLowLimit).getIssuer(),
sleState->getFieldAmount(sfHighLimit).getIssuer());
auto sleLow = view.peek(keylet::account(low));
auto sleHigh = view.peek(keylet::account(high));
AccountRootEntry<ApplyView> sleLow{keylet::account(low), view};
AccountRootEntry<ApplyView> sleHigh{keylet::account(high), view};
if (!sleLow || !sleHigh)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -778,7 +789,7 @@ deleteAMMTrustLine(
if (!sleState->isFlag(uFlags))
return tecINTERNAL; // LCOV_EXCL_LINE
adjustOwnerCount(view, !ammLow ? sleLow : sleHigh, -1, j);
adjustOwnerCount(view, !ammLow ? sleLow.mutableSle() : sleHigh.mutableSle(), -1, j);
return tesSUCCESS;
}

View File

@@ -5,6 +5,7 @@
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/OracleHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -37,7 +38,7 @@ getLedgerEntryOwner(ReadView const& view, SLE const& sle, AccountID const& accou
case ltMPTOKEN_ISSUANCE:
return sle.getAccountID(sfIssuer);
case ltSIGNER_LIST: {
auto const signerList = view.read(keylet::signerList(account));
SignerListEntry<ReadView> signerList{keylet::signerList(account), view};
if (!signerList)
return std::nullopt;
if (signerList->key() == sle.key())

View File

@@ -10,6 +10,7 @@
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/Concepts.h>
@@ -275,7 +276,7 @@ getLineIfUsable(
FreezeHandling zeroIfFrozen,
beast::Journal j)
{
auto sle = view.read(keylet::trustLine(account, issuer, currency));
RippleStateEntry<ReadView> sle{keylet::trustLine(account, issuer, currency), view};
if (!sle)
{
@@ -294,14 +295,14 @@ getLineIfUsable(
// we need to check if the associated assets have been frozen
if (view.rules().enabled(fixFrozenLPTokenTransfer))
{
auto const sleIssuer = view.read(keylet::account(issuer));
AccountRootEntry<ReadView> const sleIssuer{keylet::account(issuer), view};
if (!sleIssuer)
{
return nullptr; // LCOV_EXCL_LINE
}
if (sleIssuer->isFieldPresent(sfAMMID))
{
auto const sleAmm = view.read(keylet::amm((*sleIssuer)[sfAMMID]));
AMMEntry<ReadView> const sleAmm{keylet::amm((*sleIssuer)[sfAMMID]), view};
if (!sleAmm ||
isLPTokenFrozen(view, account, (*sleAmm)[sfAsset], (*sleAmm)[sfAsset2]))
@@ -312,7 +313,7 @@ getLineIfUsable(
}
}
return sle;
return sle.sle();
}
static STAmount
@@ -416,7 +417,8 @@ accountHolds(
{
// if the account is the issuer, and the issuance exists, their limit is
// the issuance limit minus the outstanding value
auto const issuance = view.read(keylet::mptokenIssuance(mptIssue.getMptID()));
MPTokenIssuanceEntry<ReadView> const issuance{
keylet::mptokenIssuance(mptIssue.getMptID()), view};
if (!issuance)
{
@@ -428,7 +430,7 @@ accountHolds(
return view.balanceHookMPT(issuer, mptIssue, available);
}
auto const sleMpt = view.read(keylet::mptoken(mptIssue.getMptID(), account));
MPTokenEntry<ReadView> const sleMpt{keylet::mptoken(mptIssue.getMptID(), account), view};
if (!sleMpt ||
(zeroIfFrozen == FreezeHandling::ZeroIfFrozen && isFrozen(view, account, mptIssue)))
@@ -451,7 +453,8 @@ accountHolds(
}
else if (zeroIfUnauthorized == AuthHandling::ZeroIfUnauthorized)
{
auto const sleIssuance = view.read(keylet::mptokenIssuance(mptIssue.getMptID()));
MPTokenIssuanceEntry<ReadView> const sleIssuance{
keylet::mptokenIssuance(mptIssue.getMptID()), view};
// if auth is enabled on the issuance and mpt is not authorized,
// clear amount
@@ -548,7 +551,7 @@ canAddHolding(ReadView const& view, Issue const& issue)
return tesSUCCESS; // No special checks for XRP
}
auto const issuer = view.read(keylet::account(issue.getIssuer()));
AccountRootEntry<ReadView> const issuer{keylet::account(issue.getIssuer()), view};
if (!issuer)
{
return terNO_ACCOUNT;
@@ -672,7 +675,7 @@ directSendNoFeeIOU(
"xrpl::directSendNoFeeIOU : receiver is not XRP");
// If the line exists, modify it accordingly.
if (auto const sleRippleState = view.peek(index))
if (RippleStateEntry<ApplyView> sleRippleState{index, view})
{
STAmount saBalance = sleRippleState->getFieldAmount(sfBalance);
@@ -739,13 +742,13 @@ directSendNoFeeIOU(
{
return trustDelete(
view,
sleRippleState,
sleRippleState.mutableSle(),
bSenderHigh ? uReceiverID : uSenderID,
bSenderHigh ? uSenderID : uReceiverID,
j);
}
view.update(sleRippleState);
sleRippleState.update();
return tesSUCCESS;
}
@@ -759,7 +762,7 @@ directSendNoFeeIOU(
<< to_string(uSenderID) << " -> " << to_string(uReceiverID) << " : "
<< saAmount.getFullText();
auto const sleAccount = view.peek(keylet::account(uReceiverID));
AccountRootEntry<ApplyView> const sleAccount{keylet::account(uReceiverID), view};
if (!sleAccount)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -771,7 +774,7 @@ directSendNoFeeIOU(
uSenderID,
uReceiverID,
index.key,
sleAccount,
sleAccount.mutableSle(),
false,
noRipple,
false,
@@ -956,10 +959,11 @@ accountSendIOU(
*/
TER terResult(tesSUCCESS);
SLE::pointer const sender =
uSenderID != beast::kZero ? view.peek(keylet::account(uSenderID)) : SLE::pointer();
SLE::pointer const receiver =
uReceiverID != beast::kZero ? view.peek(keylet::account(uReceiverID)) : SLE::pointer();
AccountRootEntry<ApplyView> sender{
uSenderID != beast::kZero ? view.peek(keylet::account(uSenderID)) : SLE::pointer(), view};
AccountRootEntry<ApplyView> receiver{
uReceiverID != beast::kZero ? view.peek(keylet::account(uReceiverID)) : SLE::pointer(),
view};
if (auto stream = j.trace())
{
@@ -993,7 +997,7 @@ accountSendIOU(
// Decrement XRP balance.
sender->setFieldAmount(sfBalance, sndBal - saAmount);
view.update(sender);
sender.update();
}
}
@@ -1004,7 +1008,7 @@ accountSendIOU(
receiver->setFieldAmount(sfBalance, rcvBal + saAmount);
view.creditHookIOU(xrpAccount(), uReceiverID, saAmount, -rcvBal);
view.update(receiver);
receiver.update();
}
if (auto stream = j.trace())
@@ -1052,8 +1056,8 @@ accountSendMultiIOU(
* ensure that transfers are balanced.
*/
SLE::pointer const sender =
senderID != beast::kZero ? view.peek(keylet::account(senderID)) : SLE::pointer();
AccountRootEntry<ApplyView> sender{
senderID != beast::kZero ? view.peek(keylet::account(senderID)) : SLE::pointer(), view};
if (auto stream = j.trace())
{
@@ -1084,8 +1088,9 @@ accountSendMultiIOU(
if (!amount || (senderID == receiverID))
continue;
SLE::pointer const receiver =
receiverID != beast::kZero ? view.peek(keylet::account(receiverID)) : SLE::pointer();
AccountRootEntry<ApplyView> receiver{
receiverID != beast::kZero ? view.peek(keylet::account(receiverID)) : SLE::pointer(),
view};
if (auto stream = j.trace())
{
@@ -1106,7 +1111,7 @@ accountSendMultiIOU(
receiver->setFieldAmount(sfBalance, rcvBal + amount);
view.creditHookIOU(xrpAccount(), receiverID, amount, -rcvBal);
view.update(receiver);
receiver.update();
// Take what is actually sent
takeFromSender += amount;
@@ -1136,7 +1141,7 @@ accountSendMultiIOU(
// Decrement XRP balance.
sender->setFieldAmount(sfBalance, sndBal - takeFromSender);
view.update(sender);
sender.update();
}
if (auto stream = j.trace())
@@ -1163,7 +1168,7 @@ directSendNoFeeMPT(
// Do not check MPT authorization here - it must have been checked earlier
auto const mptID = keylet::mptokenIssuance(saAmount.get<MPTIssue>().getMptID());
auto const& issuer = saAmount.getIssuer();
auto sleIssuance = view.peek(mptID);
MPTokenIssuanceEntry<ApplyView> sleIssuance{mptID, view};
if (!sleIssuance)
return tecOBJECT_NOT_FOUND;
@@ -1180,19 +1185,19 @@ directSendNoFeeMPT(
return tecPATH_DRY;
}
(*sleIssuance)[sfOutstandingAmount] += amt;
view.update(sleIssuance);
sleIssuance.update();
}
else
{
auto const mptokenID = keylet::mptoken(mptID.key, uSenderID);
if (auto sle = view.peek(mptokenID))
if (MPTokenEntry<ApplyView> sle{mptokenID, view})
{
auto const senderBalance = sle->getFieldU64(sfMPTAmount);
if (senderBalance < amt)
return tecINSUFFICIENT_FUNDS;
view.creditHookMPT(uSenderID, uReceiverID, saAmount, (*sle)[sfMPTAmount], available);
(*sle)[sfMPTAmount] = senderBalance - amt;
view.update(sle);
sle.update();
}
else
{
@@ -1205,7 +1210,7 @@ directSendNoFeeMPT(
if (outstanding >= amt)
{
sleIssuance->setFieldU64(sfOutstandingAmount, outstanding - amt);
view.update(sleIssuance);
sleIssuance.update();
}
else
{
@@ -1215,7 +1220,7 @@ directSendNoFeeMPT(
else
{
auto const mptokenID = keylet::mptoken(mptID.key, uReceiverID);
if (auto sle = view.peek(mptokenID))
if (MPTokenEntry<ApplyView> sle{mptokenID, view})
{
if (view.rules().enabled(featureMPTokensV2))
{
@@ -1226,7 +1231,7 @@ directSendNoFeeMPT(
}
view.creditHookMPT(uSenderID, uReceiverID, saAmount, (*sle)[sfMPTAmount], available);
(*sle)[sfMPTAmount] += amt;
view.update(sle);
sle.update();
}
else
{
@@ -1253,7 +1258,8 @@ directSendNoLimitMPT(
// Safe to get MPT since directSendNoLimitMPT is only called by accountSendMPT
auto const& issuer = saAmount.getIssuer();
auto const sle = view.read(keylet::mptokenIssuance(saAmount.get<MPTIssue>().getMptID()));
MPTokenIssuanceEntry<ReadView> const sle{
keylet::mptokenIssuance(saAmount.get<MPTIssue>().getMptID()), view};
if (!sle)
return tecOBJECT_NOT_FOUND;
@@ -1310,7 +1316,7 @@ directSendNoLimitMultiMPT(
{
auto const& issuer = mptIssue.getIssuer();
auto const sle = view.read(keylet::mptokenIssuance(mptIssue.getMptID()));
MPTokenIssuanceEntry<ReadView> const sle{keylet::mptokenIssuance(mptIssue.getMptID()), view};
if (!sle)
return tecOBJECT_NOT_FOUND;
@@ -1536,8 +1542,8 @@ transferXRP(
XRPL_ASSERT(from != to, "xrpl::transferXRP : sender is not receiver");
XRPL_ASSERT(amount.native(), "xrpl::transferXRP : amount is XRP");
SLE::pointer const sender = view.peek(keylet::account(from));
SLE::pointer const receiver = view.peek(keylet::account(to));
AccountRootEntry<ApplyView> sender{keylet::account(from), view};
AccountRootEntry<ApplyView> receiver{keylet::account(to), view};
if (!sender || !receiver)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -1556,10 +1562,10 @@ transferXRP(
// Decrement XRP balance.
sender->setFieldAmount(sfBalance, sender->getFieldAmount(sfBalance) - amount);
view.update(sender);
sender.update();
receiver->setFieldAmount(sfBalance, receiver->getFieldAmount(sfBalance) + amount);
view.update(receiver);
receiver.update();
return tesSUCCESS;
}

View File

@@ -17,7 +17,10 @@
namespace xrpl {
[[nodiscard]] std::optional<STAmount>
assetsToSharesDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount const& assets)
assetsToSharesDeposit(
VaultEntry<ReadView> const& vault,
MPTokenIssuanceEntry<ReadView> const& issuance,
STAmount const& assets)
{
XRPL_ASSERT(!assets.negative(), "xrpl::assetsToSharesDeposit : non-negative assets");
XRPL_ASSERT(
@@ -41,7 +44,10 @@ assetsToSharesDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount co
}
[[nodiscard]] std::optional<STAmount>
sharesToAssetsDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount const& shares)
sharesToAssetsDeposit(
VaultEntry<ReadView> const& vault,
MPTokenIssuanceEntry<ReadView> const& issuance,
STAmount const& shares)
{
XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsDeposit : non-negative shares");
XRPL_ASSERT(
@@ -65,8 +71,8 @@ sharesToAssetsDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount co
[[nodiscard]] std::optional<STAmount>
assetsToSharesWithdraw(
SLE::const_ref vault,
SLE::const_ref issuance,
VaultEntry<ReadView> const& vault,
MPTokenIssuanceEntry<ReadView> const& issuance,
STAmount const& assets,
TruncateShares truncate,
WaiveUnrealizedLoss waive)
@@ -94,8 +100,8 @@ assetsToSharesWithdraw(
[[nodiscard]] std::optional<STAmount>
sharesToAssetsWithdraw(
SLE::const_ref vault,
SLE::const_ref issuance,
VaultEntry<ReadView> const& vault,
MPTokenIssuanceEntry<ReadView> const& issuance,
STAmount const& shares,
WaiveUnrealizedLoss waive)
{
@@ -118,7 +124,10 @@ sharesToAssetsWithdraw(
}
[[nodiscard]] bool
isSoleShareholder(ReadView const& view, AccountID const& account, SLE::const_ref issuance)
isSoleShareholder(
ReadView const& view,
AccountID const& account,
MPTokenIssuanceEntry<ReadView> const& issuance)
{
XRPL_ASSERT(
issuance && issuance->getType() == ltMPTOKEN_ISSUANCE,
@@ -130,7 +139,7 @@ isSoleShareholder(ReadView const& view, AccountID const& account, SLE::const_ref
auto const shareMPTID =
makeMptID(issuance->getFieldU32(sfSequence), issuance->getAccountID(sfIssuer));
auto const sleToken = view.read(keylet::mptoken(shareMPTID, account));
MPTokenEntry<ReadView> sleToken{keylet::mptoken(shareMPTID, account), view};
if (!sleToken)
return false; // LCOV_EXCL_LINE

View File

@@ -13,6 +13,7 @@
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/ledger/helpers/OfferHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -225,7 +226,7 @@ AccountDelete::preclaim(PreclaimContext const& ctx)
AccountID const account{ctx.tx[sfAccount]};
AccountID const dst{ctx.tx[sfDestination]};
auto sleDst = ctx.view.read(keylet::account(dst));
AccountRootEntry<ReadView> sleDst{keylet::account(dst), ctx.view};
if (!sleDst)
return tecNO_DST;
@@ -249,7 +250,7 @@ AccountDelete::preclaim(PreclaimContext const& ctx)
}
}
auto sleAccount = ctx.view.read(keylet::account(account));
AccountRootEntry<ReadView> sleAccount{keylet::account(account), ctx.view};
XRPL_ASSERT(sleAccount, "xrpl::AccountDelete::preclaim : non-null account");
if (!sleAccount)
return terNO_ACCOUNT;
@@ -263,8 +264,9 @@ AccountDelete::preclaim(PreclaimContext const& ctx)
Keylet const first = keylet::nftokenPageMin(account);
Keylet const last = keylet::nftokenPageMax(account);
auto const cp = ctx.view.read(
Keylet(ltNFTOKEN_PAGE, ctx.view.succ(first.key, last.key.next()).value_or(last.key)));
NFTokenPageEntry<ReadView> const cp{
Keylet(ltNFTOKEN_PAGE, ctx.view.succ(first.key, last.key.next()).value_or(last.key)),
ctx.view};
if (cp)
return tecHAS_OBLIGATIONS;
@@ -314,7 +316,7 @@ AccountDelete::preclaim(PreclaimContext const& ctx)
{
// Make sure any directory node types that we find are the kind
// we can delete.
auto sleItem = ctx.view.read(keylet::child(dirEntry));
ReadOnlySLE sleItem{keylet::child(dirEntry), ctx.view};
if (!sleItem)
{
// Directory node has an invalid index. Bail out.
@@ -343,11 +345,11 @@ AccountDelete::preclaim(PreclaimContext const& ctx)
TER
AccountDelete::doApply()
{
auto src = view().peek(keylet::account(accountID_));
AccountRootEntry<ApplyView> src{keylet::account(accountID_), view()};
XRPL_ASSERT(src, "xrpl::AccountDelete::doApply : non-null source account");
auto const dstID = ctx_.tx[sfDestination];
auto dst = view().peek(keylet::account(dstID));
AccountRootEntry<ApplyView> dst{keylet::account(dstID), view()};
XRPL_ASSERT(dst, "xrpl::AccountDelete::doApply : non-null destination account");
if (!src || !dst)
@@ -355,8 +357,8 @@ AccountDelete::doApply()
if (ctx_.tx.isFieldPresent(sfCredentialIDs))
{
if (auto err =
verifyDepositPreauth(ctx_.tx, ctx_.view(), accountID_, dstID, dst, ctx_.journal);
if (auto err = verifyDepositPreauth(
ctx_.tx, ctx_.view(), accountID_, dstID, dst.sle(), ctx_.journal);
!isTesSuccess(err))
return err;
}
@@ -409,8 +411,8 @@ AccountDelete::doApply()
if (remainingBalance > XRPAmount(0) && dst->isFlag(lsfPasswordSpent))
dst->clearFlag(lsfPasswordSpent);
view().update(dst);
view().erase(src);
dst.update();
src.erase();
return tesSUCCESS;
}

View File

@@ -7,6 +7,7 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
@@ -170,7 +171,7 @@ AccountSet::preclaim(PreclaimContext const& ctx)
{
auto const id = ctx.tx[sfAccount];
auto const sle = ctx.view.read(keylet::account(id));
AccountRootEntry<ReadView> const sle{keylet::account(id), ctx.view};
if (!sle)
return terNO_ACCOUNT;
@@ -224,7 +225,7 @@ AccountSet::preclaim(PreclaimContext const& ctx)
TER
AccountSet::doApply()
{
auto const sle = view().peek(keylet::account(accountID_));
AccountRootEntry<ApplyView> sle{keylet::account(accountID_), view()};
if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -312,7 +313,8 @@ AccountSet::doApply()
return tecNEED_MASTER_KEY;
}
if ((!sle->isFieldPresent(sfRegularKey)) && (!view().peek(keylet::signerList(accountID_))))
if ((!sle->isFieldPresent(sfRegularKey)) &&
(!SignerListEntry<ApplyView>{keylet::signerList(accountID_), view()}))
{
// Account has no regular key or multi-signer signer list.
return tecNO_ALTERNATIVE_KEY;
@@ -582,7 +584,7 @@ AccountSet::doApply()
if (uFlagsIn != uFlagsOut)
sle->setFieldU32(sfFlags, uFlagsOut);
ctx_.view().update(sle);
sle.update();
return tesSUCCESS;
}

View File

@@ -3,6 +3,7 @@
#include <xrpl/basics/Slice.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/PublicKey.h>
@@ -25,7 +26,7 @@ SetRegularKey::calculateBaseFee(ReadView const& view, STTx const& tx)
{
if (calcAccountID(PublicKey(makeSlice(spk))) == id)
{
auto const sle = view.read(keylet::account(id));
AccountRootEntry<ReadView> const sle{keylet::account(id), view};
if (sle && !sle->isFlag(lsfPasswordSpent))
{
@@ -53,7 +54,7 @@ SetRegularKey::preflight(PreflightContext const& ctx)
TER
SetRegularKey::doApply()
{
auto const sle = view().peek(keylet::account(accountID_));
AccountRootEntry<ApplyView> sle{keylet::account(accountID_), view()};
if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -67,13 +68,14 @@ SetRegularKey::doApply()
else
{
// Account has disabled master key and no multi-signer signer list.
if (sle->isFlag(lsfDisableMaster) && !view().peek(keylet::signerList(accountID_)))
if (sle->isFlag(lsfDisableMaster) &&
!SignerListEntry<ApplyView>{keylet::signerList(accountID_), view()})
return tecNO_ALTERNATIVE_KEY;
sle->makeFieldAbsent(sfRegularKey);
}
ctx_.view().update(sle);
sle.update();
return tesSUCCESS;
}

View File

@@ -8,6 +8,7 @@
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -187,7 +188,7 @@ removeSignersFromLedger(
{
// We have to examine the current SignerList so we know how much to
// reduce the OwnerCount.
SLE::pointer const signers = view.peek(signerListKeylet);
SignerListEntry<ApplyView> signers{signerListKeylet, view};
// If the signer list doesn't exist we've already succeeded in deleting it.
if (!signers)
@@ -215,10 +216,10 @@ removeSignersFromLedger(
// LCOV_EXCL_STOP
}
adjustOwnerCount(
view, view.peek(accountKeylet), removeFromOwnerCount, registry.getJournal("View"));
AccountRootEntry<ApplyView> account{accountKeylet, view};
adjustOwnerCount(view, account.mutableSle(), removeFromOwnerCount, registry.getJournal("View"));
view.erase(signers);
signers.erase();
return tesSUCCESS;
}
@@ -311,7 +312,7 @@ SignerListSet::replaceSignerList()
ctx_.registry, view(), accountKeylet, ownerDirKeylet, signerListKeylet, j_))
return ter;
auto const sle = view().peek(accountKeylet);
AccountRootEntry<ApplyView> const sle{accountKeylet, view()};
if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -330,8 +331,9 @@ SignerListSet::replaceSignerList()
return tecINSUFFICIENT_RESERVE;
// Everything's ducky. Add the ltSIGNER_LIST to the ledger.
auto signerList = std::make_shared<SLE>(signerListKeylet);
view().insert(signerList);
SignerListEntry<ApplyView> signerList{signerListKeylet, view()};
signerList.newSLE();
signerList.insert();
writeSignersToSLE(signerList, flags);
auto viewJ = ctx_.registry.get().getJournal("View");
@@ -349,7 +351,7 @@ SignerListSet::replaceSignerList()
// If we succeeded, the new entry counts against the
// creator's reserve.
adjustOwnerCount(view(), sle, kAddedOwnerCount, viewJ);
adjustOwnerCount(view(), sle.mutableSle(), kAddedOwnerCount, viewJ);
return tesSUCCESS;
}
@@ -359,7 +361,7 @@ SignerListSet::destroySignerList()
auto const accountKeylet = keylet::account(accountID_);
// Destroying the signer list is only allowed if either the master key
// is enabled or there is a regular key.
SLE::pointer const ledgerEntry = view().peek(accountKeylet);
AccountRootEntry<ApplyView> const ledgerEntry{accountKeylet, view()};
if (!ledgerEntry)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -373,7 +375,7 @@ SignerListSet::destroySignerList()
}
void
SignerListSet::writeSignersToSLE(SLE::pointer const& ledgerEntry, std::uint32_t flags) const
SignerListSet::writeSignersToSLE(SignerListEntry<ApplyView>& ledgerEntry, std::uint32_t flags) const
{
// Assign the quorum, default SignerListID, and flags.
if (ctx_.view().rules().enabled(fixIncludeKeyletFields))

View File

@@ -12,6 +12,7 @@
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -797,24 +798,27 @@ readOrpeekBridge(F&& getter, STXChainBridge const& bridgeSpec)
return tryGet(STXChainBridge::ChainType::Issuing);
}
SLE::pointer
BridgeEntry<ApplyView>
peekBridge(ApplyView& v, STXChainBridge const& bridgeSpec)
{
return readOrpeekBridge<SLE>(
[&v](STXChainBridge const& b, STXChainBridge::ChainType ct) -> SLE::pointer {
return v.peek(keylet::bridge(b, ct));
},
bridgeSpec);
return BridgeEntry<ApplyView>{
readOrpeekBridge<SLE>(
[&v](STXChainBridge const& b, STXChainBridge::ChainType ct) -> std::shared_ptr<SLE> {
return v.peek(keylet::bridge(b, ct));
},
bridgeSpec),
v};
}
SLE::const_pointer
BridgeEntry<ReadView>
readBridge(ReadView const& v, STXChainBridge const& bridgeSpec)
{
return readOrpeekBridge<SLE const>(
[&v](STXChainBridge const& b, STXChainBridge::ChainType ct) -> SLE::const_pointer {
return v.read(keylet::bridge(b, ct));
},
bridgeSpec);
return BridgeEntry<ReadView>{
readOrpeekBridge<SLE const>(
[&v](STXChainBridge const& b, STXChainBridge::ChainType ct)
-> std::shared_ptr<SLE const> { return v.read(keylet::bridge(b, ct)); },
bridgeSpec),
v};
}
// Precondition: all the claims in the range are consistent. They must sign for
@@ -2008,7 +2012,7 @@ XChainCreateClaimID::doApply()
if (!sleAcct)
return tecINTERNAL; // LCOV_EXCL_LINE
auto const sleBridge = peekBridge(ctx_.view(), bridgeSpec);
auto sleBridge = peekBridge(ctx_.view(), bridgeSpec);
if (!sleBridge)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -2049,7 +2053,7 @@ XChainCreateClaimID::doApply()
adjustOwnerCount(ctx_.view(), sleAcct, 1, ctx_.journal);
ctx_.view().insert(sleClaimID);
ctx_.view().update(sleBridge);
sleBridge.update();
ctx_.view().update(sleAcct);
return tesSUCCESS;
@@ -2192,7 +2196,7 @@ XChainCreateAccountCommit::doApply()
if (!sle)
return tecINTERNAL; // LCOV_EXCL_LINE
auto const sleBridge = peekBridge(psb, bridge);
auto sleBridge = peekBridge(psb, bridge);
if (!sleBridge)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -2220,7 +2224,7 @@ XChainCreateAccountCommit::doApply()
return thTer;
(*sleBridge)[sfXChainAccountCreateCount] = (*sleBridge)[sfXChainAccountCreateCount] + 1;
psb.update(sleBridge);
sleBridge.update();
psb.apply(ctx_.rawView());

View File

@@ -4,6 +4,7 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/SField.h>
@@ -25,7 +26,7 @@ CheckCancel::preflight(PreflightContext const& ctx)
TER
CheckCancel::preclaim(PreclaimContext const& ctx)
{
auto const sleCheck = ctx.view.read(keylet::check(ctx.tx[sfCheckID]));
CheckEntry<ReadView> sleCheck{keylet::check(ctx.tx[sfCheckID]), ctx.view};
if (!sleCheck)
{
JLOG(ctx.j.warn()) << "Check does not exist.";
@@ -54,7 +55,7 @@ CheckCancel::preclaim(PreclaimContext const& ctx)
TER
CheckCancel::doApply()
{
auto const sleCheck = view().peek(keylet::check(ctx_.tx[sfCheckID]));
CheckEntry<ApplyView> sleCheck{keylet::check(ctx_.tx[sfCheckID]), view()};
if (!sleCheck)
{
// Error should have been caught in preclaim.
@@ -91,11 +92,11 @@ CheckCancel::doApply()
}
// If we succeeded, update the check owner's reserve.
auto const sleSrc = view().peek(keylet::account(srcId));
adjustOwnerCount(view(), sleSrc, -1, viewJ);
AccountRootEntry<ApplyView> sleSrc{keylet::account(srcId), view()};
adjustOwnerCount(view(), sleSrc.mutableSle(), -1, viewJ);
// Remove check from ledger.
view().erase(sleCheck);
sleCheck.erase();
return tesSUCCESS;
}

View File

@@ -8,6 +8,7 @@
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Asset.h>
@@ -80,7 +81,7 @@ CheckCash::preflight(PreflightContext const& ctx)
TER
CheckCash::preclaim(PreclaimContext const& ctx)
{
auto const sleCheck = ctx.view.read(keylet::check(ctx.tx[sfCheckID]));
CheckEntry<ReadView> sleCheck{keylet::check(ctx.tx[sfCheckID]), ctx.view};
if (!sleCheck)
{
JLOG(ctx.j.warn()) << "Check does not exist.";
@@ -105,8 +106,8 @@ CheckCash::preclaim(PreclaimContext const& ctx)
// LCOV_EXCL_STOP
}
{
auto const sleSrc = ctx.view.read(keylet::account(srcId));
auto const sleDst = ctx.view.read(keylet::account(dstId));
AccountRootEntry<ReadView> sleSrc{keylet::account(srcId), ctx.view};
AccountRootEntry<ReadView> sleDst{keylet::account(dstId), ctx.view};
if (!sleSrc || !sleDst)
{
// If the check exists this should never occur.
@@ -191,10 +192,10 @@ 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));
RippleStateEntry<ReadView> sleTrustLine{
keylet::trustLine(dstId, issuerId, currency), ctx.view};
auto const sleIssuer = ctx.view.read(keylet::account(issuerId));
AccountRootEntry<ReadView> sleIssuer{keylet::account(issuerId), ctx.view};
if (!sleIssuer)
{
JLOG(ctx.j.warn()) << "Can't receive IOUs from "
@@ -246,7 +247,7 @@ CheckCash::preclaim(PreclaimContext const& ctx)
return tesSUCCESS;
},
[&](MPTIssue const& issue) -> TER {
auto const sleIssuer = ctx.view.read(keylet::account(issuerId));
AccountRootEntry<ReadView> sleIssuer{keylet::account(issuerId), ctx.view};
if (!sleIssuer)
{
JLOG(ctx.j.warn()) << "Can't receive MPTs from "
@@ -581,7 +582,8 @@ CheckCash::doApply()
}
// If we succeeded, update the check owner's reserve.
adjustOwnerCount(psb, psb.peek(keylet::account(srcId)), -1, viewJ);
AccountRootEntry<ApplyView> sleSrcAccount{keylet::account(srcId), psb};
adjustOwnerCount(psb, sleSrcAccount.mutableSle(), -1, viewJ);
// Remove check from ledger.
psb.erase(sleCheck);

View File

@@ -7,6 +7,7 @@
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Asset.h>
@@ -79,7 +80,7 @@ CheckCreate::preclaim(PreclaimContext const& ctx)
{
AccountID const dstId{ctx.tx[sfDestination]};
AccountID const srcId{ctx.tx[sfAccount]};
auto const sleDst = ctx.view.read(keylet::account(dstId));
AccountRootEntry<ReadView> sleDst{keylet::account(dstId), ctx.view};
if (!sleDst)
{
JLOG(ctx.j.warn()) << "Destination account does not exist.";
@@ -94,7 +95,7 @@ CheckCreate::preclaim(PreclaimContext const& ctx)
// because all writes to pseudo-account discriminator fields **are**
// amendment gated, hence the behaviour of this check will always match the
// currently active amendments.
if (isPseudoAccount(sleDst))
if (isPseudoAccount(sleDst.sle()))
return tecNO_PERMISSION;
if (sleDst->isFlag(lsfRequireDestTag) && !ctx.tx.isFieldPresent(sfDestinationTag))
@@ -126,8 +127,8 @@ 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));
RippleStateEntry<ReadView> sleTrust{
keylet::trustLine(srcId, issuerId, issue.currency), ctx.view};
if (sleTrust &&
sleTrust->isFlag((issuerId > srcId) ? lsfHighFreeze : lsfLowFreeze))
{
@@ -138,8 +139,8 @@ 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));
RippleStateEntry<ReadView> sleTrust{
keylet::trustLine(issuerId, dstId, issue.currency), ctx.view};
if (sleTrust &&
sleTrust->isFlag((dstId > issuerId) ? lsfHighFreeze : lsfLowFreeze))
{
@@ -187,7 +188,7 @@ CheckCreate::preclaim(PreclaimContext const& ctx)
TER
CheckCreate::doApply()
{
auto const sle = view().peek(keylet::account(accountID_));
AccountRootEntry<ApplyView> sle{keylet::account(accountID_), view()};
if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -205,7 +206,8 @@ CheckCreate::doApply()
// Check sequence. For more explanation see comments in SeqProxy.h.
std::uint32_t const seq = ctx_.tx.getSeqValue();
Keylet const checkKeylet = keylet::check(accountID_, seq);
auto sleCheck = std::make_shared<SLE>(checkKeylet);
CheckEntry<ApplyView> sleCheck{checkKeylet, view()};
sleCheck.newSLE();
sleCheck->setAccountID(sfAccount, accountID_);
AccountID const dstAccountId = ctx_.tx[sfDestination];
@@ -221,7 +223,7 @@ CheckCreate::doApply()
if (auto const expiry = ctx_.tx[~sfExpiration])
sleCheck->setFieldU32(sfExpiration, *expiry);
view().insert(sleCheck);
sleCheck.insert();
auto viewJ = ctx_.registry.get().getJournal("View");
// If it's not a self-send (and it shouldn't be), add Check to the
@@ -253,7 +255,7 @@ CheckCreate::doApply()
sleCheck->setFieldU64(sfOwnerNode, *page);
}
// If we succeeded, the new entry counts against the creator's reserve.
adjustOwnerCount(view(), sle, 1, viewJ);
adjustOwnerCount(view(), sle.mutableSle(), 1, viewJ);
return tesSUCCESS;
}

View File

@@ -4,6 +4,7 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -63,7 +64,7 @@ CredentialAccept::preclaim(PreclaimContext const& ctx)
return tecNO_ISSUER;
}
auto const sleCred = ctx.view.read(keylet::credential(subject, issuer, credType));
CredentialEntry<ReadView> sleCred{keylet::credential(subject, issuer, credType), ctx.view};
if (!sleCred)
{
JLOG(ctx.j.warn()) << "No credential: " << to_string(subject) << ", " << to_string(issuer)
@@ -87,8 +88,8 @@ CredentialAccept::doApply()
AccountID const issuer{ctx_.tx[sfIssuer]};
// Both exist as credential object exist itself (checked in preclaim)
auto const sleSubject = view().peek(keylet::account(accountID_));
auto const sleIssuer = view().peek(keylet::account(issuer));
AccountRootEntry<ApplyView> sleSubject{keylet::account(accountID_), view()};
AccountRootEntry<ApplyView> sleIssuer{keylet::account(issuer), view()};
if (!sleSubject || !sleIssuer)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -102,7 +103,7 @@ CredentialAccept::doApply()
auto const credType(ctx_.tx[sfCredentialType]);
Keylet const credentialKey = keylet::credential(accountID_, issuer, credType);
auto const sleCred = view().peek(credentialKey); // Checked in preclaim()
CredentialEntry<ApplyView> sleCred{credentialKey, view()}; // Checked in preclaim()
if (!sleCred)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -110,15 +111,15 @@ CredentialAccept::doApply()
{
JLOG(j_.trace()) << "Credential is expired: " << sleCred->getText();
// delete expired credentials even if the transaction failed
auto const err = credentials::deleteSLE(view(), sleCred, j_);
auto const err = credentials::deleteSLE(view(), sleCred.mutableSle(), j_);
return isTesSuccess(err) ? tecEXPIRED : err;
}
sleCred->setFieldU32(sfFlags, lsfAccepted);
view().update(sleCred);
sleCred.update();
adjustOwnerCount(view(), sleIssuer, -1, j_);
adjustOwnerCount(view(), sleSubject, 1, j_);
adjustOwnerCount(view(), sleIssuer.mutableSle(), -1, j_);
adjustOwnerCount(view(), sleSubject.mutableSle(), 1, j_);
return tesSUCCESS;
}

View File

@@ -7,6 +7,7 @@
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> // IWYU pragma: keep
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Keylet.h>
@@ -106,7 +107,8 @@ CredentialCreate::doApply()
auto const credType(ctx_.tx[sfCredentialType]);
Keylet const credentialKey = keylet::credential(subject, accountID_, credType);
auto const sleCred = std::make_shared<SLE>(credentialKey);
CredentialEntry<ApplyView> sleCred{credentialKey, view()};
sleCred.newSLE();
if (!sleCred)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -126,7 +128,7 @@ CredentialCreate::doApply()
sleCred->setFieldU32(sfExpiration, *optExp);
}
auto const sleIssuer = view().peek(keylet::account(accountID_));
AccountRootEntry<ApplyView> sleIssuer{keylet::account(accountID_), view()};
if (!sleIssuer)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -153,7 +155,7 @@ CredentialCreate::doApply()
return tecDIR_FULL;
sleCred->setFieldU64(sfIssuerNode, *page);
adjustOwnerCount(view(), sleIssuer, 1, j_);
adjustOwnerCount(view(), sleIssuer.mutableSle(), 1, j_);
}
if (subject == accountID_)
@@ -173,7 +175,7 @@ CredentialCreate::doApply()
sleCred->setFieldU64(sfSubjectNode, *page);
}
view().insert(sleCred);
sleCred.insert();
return tesSUCCESS;
}

View File

@@ -3,6 +3,7 @@
#include <xrpl/basics/Log.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -80,7 +81,7 @@ CredentialDelete::doApply()
auto const issuer = ctx_.tx[~sfIssuer].value_or(accountID_);
auto const credType(ctx_.tx[sfCredentialType]);
auto const sleCred = view().peek(keylet::credential(subject, issuer, credType));
CredentialEntry<ApplyView> sleCred{keylet::credential(subject, issuer, credType), view()};
if (!sleCred)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -91,7 +92,7 @@ CredentialDelete::doApply()
return tecNO_PERMISSION;
}
return deleteSLE(view(), sleCred, j_);
return deleteSLE(view(), sleCred.mutableSle(), j_);
}
void

View File

@@ -5,6 +5,7 @@
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/SField.h>
@@ -72,25 +73,25 @@ DelegateSet::preclaim(PreclaimContext const& ctx)
TER
DelegateSet::doApply()
{
auto const sleOwner = ctx_.view().peek(keylet::account(accountID_));
AccountRootEntry<ApplyView> sleOwner{keylet::account(accountID_), ctx_.view()};
if (!sleOwner)
return tefINTERNAL; // LCOV_EXCL_LINE
auto const& authAccount = ctx_.tx[sfAuthorize];
auto const delegateKey = keylet::delegate(accountID_, authAccount);
auto sle = ctx_.view().peek(delegateKey);
DelegateEntry<ApplyView> sle{delegateKey, ctx_.view()};
if (sle)
{
auto const& permissions = ctx_.tx.getFieldArray(sfPermissions);
if (permissions.empty())
{
// if permissions array is empty, delete the ledger object.
return deleteDelegate(view(), sle, j_);
return deleteDelegate(view(), sle.mutableSle(), j_);
}
sle->setFieldArray(sfPermissions, permissions);
ctx_.view().update(sle);
sle.update();
return tesSUCCESS;
}
@@ -104,7 +105,7 @@ DelegateSet::doApply()
if (preFeeBalance_ < reserve)
return tecINSUFFICIENT_RESERVE;
sle = std::make_shared<SLE>(delegateKey);
sle.newSLE();
sle->setAccountID(sfAccount, accountID_);
sle->setAccountID(sfAuthorize, authAccount);
@@ -129,8 +130,8 @@ DelegateSet::doApply()
(*sle)[sfDestinationNode] = *destPage;
ctx_.view().insert(sle);
adjustOwnerCount(ctx_.view(), sleOwner, 1, ctx_.journal);
sle.insert();
adjustOwnerCount(ctx_.view(), sleOwner.mutableSle(), 1, ctx_.journal);
return tesSUCCESS;
}
@@ -166,11 +167,11 @@ DelegateSet::deleteDelegate(ApplyView& view, SLE::ref sle, beast::Journal j)
}
// Only the delegating account's owner count was incremented on creation
auto const sleOwner = view.peek(keylet::account(delegator));
AccountRootEntry<ApplyView> sleOwner{keylet::account(delegator), view};
if (!sleOwner)
return tecINTERNAL; // LCOV_EXCL_LINE
adjustOwnerCount(view, sleOwner, -1, j);
adjustOwnerCount(view, sleOwner.mutableSle(), -1, j);
view.erase(sle);

View File

@@ -268,8 +268,9 @@ AMMClawback::applyGuts(Sandbox& sb)
}
}
AMMEntry<ApplyView> ammEntry{ammSle, sb};
auto const res =
AMMWithdraw::deleteAMMAccountIfEmpty(sb, ammSle, newLPTokenBalance, asset, asset2, j_);
AMMWithdraw::deleteAMMAccountIfEmpty(sb, ammEntry, newLPTokenBalance, asset, asset2, j_);
if (!res.second)
return res.first; // LCOV_EXCL_LINE

View File

@@ -10,6 +10,7 @@
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/AccountID.h>
@@ -347,8 +348,8 @@ 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));
RippleStateEntry<ApplyView> sleRippleState{
keylet::trustLine(accountId, issue), sb};
if (!sleRippleState)
{
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -356,7 +357,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;
});

View File

@@ -446,8 +446,9 @@ AMMWithdraw::applyGuts(Sandbox& sb)
}
}
AMMEntry<ApplyView> ammEntry{ammSle, sb};
auto const res = deleteAMMAccountIfEmpty(
sb, ammSle, newLPTokenBalance, ctx_.tx[sfAsset], ctx_.tx[sfAsset2], j_);
sb, ammEntry, newLPTokenBalance, ctx_.tx[sfAsset], ctx_.tx[sfAsset2], j_);
// LCOV_EXCL_START
if (!res.second)
return {res.first, false};
@@ -797,7 +798,7 @@ AMMWithdraw::equalWithdrawTokens(
std::pair<TER, bool>
AMMWithdraw::deleteAMMAccountIfEmpty(
Sandbox& sb,
SLE::pointer const ammSle,
AMMEntry<ApplyView>& ammSle,
STAmount const& lpTokenBalance,
Asset const& asset1,
Asset const& asset2,
@@ -817,7 +818,7 @@ AMMWithdraw::deleteAMMAccountIfEmpty(
if (updateBalance)
{
ammSle->setFieldAmount(sfLPTokenBalance, lpTokenBalance);
sb.update(ammSle);
ammSle.update();
}
return {ter, true};

View File

@@ -5,6 +5,7 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Keylet.h>
@@ -27,11 +28,11 @@ DIDDelete::preflight(PreflightContext const& ctx)
TER
DIDDelete::deleteSLE(ApplyContext& ctx, Keylet sleKeylet, AccountID const owner)
{
auto const sle = ctx.view().peek(sleKeylet);
WritableSLE sle{sleKeylet, ctx.view()};
if (!sle)
return tecNO_ENTRY;
return DIDDelete::deleteSLE(ctx.view(), sle, owner, ctx.journal);
return DIDDelete::deleteSLE(ctx.view(), sle.mutableSle(), owner, ctx.journal);
}
TER
@@ -46,12 +47,12 @@ DIDDelete::deleteSLE(ApplyView& view, SLE::pointer sle, AccountID const owner, b
// LCOV_EXCL_STOP
}
auto const sleOwner = view.peek(keylet::account(owner));
AccountRootEntry<ApplyView> sleOwner{keylet::account(owner), view};
if (!sleOwner)
return tecINTERNAL; // LCOV_EXCL_LINE
adjustOwnerCount(view, sleOwner, -1, j);
view.update(sleOwner);
adjustOwnerCount(view, sleOwner.mutableSle(), -1, j);
sleOwner.update();
// Remove object from ledger
view.erase(sle);

View File

@@ -5,6 +5,7 @@
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -63,9 +64,9 @@ DIDSet::preflight(PreflightContext const& ctx)
}
static TER
addSLE(ApplyContext& ctx, SLE::ref sle, AccountID const& owner)
addSLE(ApplyContext& ctx, DIDEntry<ApplyView>& sle, AccountID const& owner)
{
auto const sleAccount = ctx.view().peek(keylet::account(owner));
AccountRootEntry<ApplyView> sleAccount{keylet::account(owner), ctx.view()};
if (!sleAccount)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -79,7 +80,7 @@ addSLE(ApplyContext& ctx, SLE::ref sle, AccountID const& owner)
}
// Add ledger object to ledger
ctx.view().insert(sle);
sle.insert();
// Add ledger object to owner's page
{
@@ -89,8 +90,8 @@ addSLE(ApplyContext& ctx, SLE::ref sle, AccountID const& owner)
return tecDIR_FULL; // LCOV_EXCL_LINE
(*sle)[sfOwnerNode] = *page;
}
adjustOwnerCount(ctx.view(), sleAccount, 1, ctx.journal);
ctx.view().update(sleAccount);
adjustOwnerCount(ctx.view(), sleAccount.mutableSle(), 1, ctx.journal);
sleAccount.update();
return tesSUCCESS;
}
@@ -100,7 +101,8 @@ DIDSet::doApply()
{
// Edit ledger object if it already exists
Keylet const didKeylet = keylet::did(accountID_);
if (auto const sleDID = ctx_.view().peek(didKeylet))
DIDEntry<ApplyView> sleDID{didKeylet, ctx_.view()};
if (sleDID)
{
auto update = [&](auto const& sField) {
if (auto const field = ctx_.tx[~sField])
@@ -124,12 +126,12 @@ DIDSet::doApply()
{
return tecEMPTY_DID;
}
ctx_.view().update(sleDID);
sleDID.update();
return tesSUCCESS;
}
// Create new ledger object otherwise
auto const sleDID = std::make_shared<SLE>(didKeylet);
sleDID.newSLE();
(*sleDID)[sfAccount] = accountID_;
auto set = [&](auto const& sField) {

View File

@@ -7,6 +7,7 @@
#include <xrpl/ledger/helpers/EscrowHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Concepts.h>
@@ -73,7 +74,7 @@ escrowCancelPreclaimHelper<MPTIssue>(
// If the mpt does not exist, return tecOBJECT_NOT_FOUND
auto const issuanceKey = keylet::mptokenIssuance(amount.get<MPTIssue>().getMptID());
auto const sleIssuance = ctx.view.read(issuanceKey);
MPTokenIssuanceEntry<ReadView> sleIssuance{issuanceKey, ctx.view};
if (!sleIssuance)
return tecOBJECT_NOT_FOUND;
@@ -93,7 +94,7 @@ EscrowCancel::preclaim(PreclaimContext const& ctx)
if (ctx.view.rules().enabled(featureTokenEscrow))
{
auto const k = keylet::escrow(ctx.tx[sfOwner], ctx.tx[sfOfferSequence]);
auto const slep = ctx.view.read(k);
EscrowEntry<ReadView> slep{k, ctx.view};
if (!slep)
return tecNO_TARGET;
@@ -118,7 +119,7 @@ TER
EscrowCancel::doApply()
{
auto const k = keylet::escrow(ctx_.tx[sfOwner], ctx_.tx[sfOfferSequence]);
auto const slep = ctx_.view().peek(k);
EscrowEntry<ApplyView> slep{k, ctx_.view()};
if (!slep)
{
if (ctx_.view().rules().enabled(featureTokenEscrow))
@@ -163,7 +164,7 @@ EscrowCancel::doApply()
}
}
auto const sle = ctx_.view().peek(keylet::account(account));
AccountRootEntry<ApplyView> sle{keylet::account(account), ctx_.view()};
STAmount const amount = slep->getFieldAmount(sfAmount);
// Transfer amount back to the owner
@@ -183,7 +184,8 @@ EscrowCancel::doApply()
return escrowUnlockApplyHelper<T>(
ctx_.view(),
kParityRate,
ctx_.view().rules().enabled(fixCleanup3_2_0) ? sle : slep,
ctx_.view().rules().enabled(fixCleanup3_2_0) ? sle.mutableSle()
: slep.mutableSle(),
preFeeBalance_,
amount,
issuer,
@@ -209,11 +211,11 @@ EscrowCancel::doApply()
}
}
adjustOwnerCount(ctx_.view(), sle, -1, ctx_.journal);
ctx_.view().update(sle);
adjustOwnerCount(ctx_.view(), sle.mutableSle(), -1, ctx_.journal);
sle.update();
// Remove escrow from ledger
ctx_.view().erase(slep);
slep.erase();
return tesSUCCESS;
}

View File

@@ -11,6 +11,7 @@
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Concepts.h>
@@ -201,14 +202,15 @@ escrowCreatePreclaimHelper<Issue>(
return tecNO_PERMISSION;
// If the lsfAllowTrustLineLocking is not enabled, return tecNO_PERMISSION
auto const sleIssuer = ctx.view.read(keylet::account(issuer));
AccountRootEntry<ReadView> sleIssuer{keylet::account(issuer), ctx.view};
if (!sleIssuer)
return tecNO_ISSUER;
if (!sleIssuer->isFlag(lsfAllowTrustLineLocking))
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));
RippleStateEntry<ReadView> sleRippleState{
keylet::trustLine(account, issuer, issue.currency), ctx.view};
if (!sleRippleState)
return tecNO_LINE;
@@ -272,7 +274,7 @@ escrowCreatePreclaimHelper<MPTIssue>(
// If the mpt does not exist, return tecOBJECT_NOT_FOUND
auto const issuanceKey = keylet::mptokenIssuance(amount.get<MPTIssue>().getMptID());
auto const sleIssuance = ctx.view.read(issuanceKey);
MPTokenIssuanceEntry<ReadView> sleIssuance{issuanceKey, ctx.view};
if (!sleIssuance)
return tecOBJECT_NOT_FOUND;
@@ -341,7 +343,7 @@ EscrowCreate::preclaim(PreclaimContext const& ctx)
AccountID const account{ctx.tx[sfAccount]};
AccountID const dest{ctx.tx[sfDestination]};
auto const sled = ctx.view.read(keylet::account(dest));
AccountRootEntry<ReadView> sled{keylet::account(dest), ctx.view};
if (!sled)
return tecNO_DST;
@@ -349,7 +351,7 @@ EscrowCreate::preclaim(PreclaimContext const& ctx)
// because all writes to pseudo-account discriminator fields **are**
// amendment gated, hence the behaviour of this check will always match the
// currently active amendments.
if (isPseudoAccount(sled))
if (isPseudoAccount(sled.sle()))
return tecNO_PERMISSION;
if (!isXRP(amount))
@@ -427,7 +429,7 @@ EscrowCreate::doApply()
if (ctx_.tx[~sfFinishAfter] && after(closeTime, ctx_.tx[sfFinishAfter]))
return tecNO_PERMISSION;
auto const sle = ctx_.view().peek(keylet::account(accountID_));
AccountRootEntry<ApplyView> sle{keylet::account(accountID_), ctx_.view()};
if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -449,7 +451,7 @@ EscrowCreate::doApply()
// Check destination account
{
auto const sled = ctx_.view().read(keylet::account(ctx_.tx[sfDestination]));
AccountRootEntry<ReadView> sled{keylet::account(ctx_.tx[sfDestination]), ctx_.view()};
if (!sled)
return tecNO_DST; // LCOV_EXCL_LINE
if (sled->isFlag(lsfRequireDestTag) && !ctx_.tx[~sfDestinationTag])
@@ -459,7 +461,8 @@ EscrowCreate::doApply()
// Create escrow in ledger. Note that we use the value from the
// sequence or ticket. For more explanation see comments in SeqProxy.h.
Keylet const escrowKeylet = keylet::escrow(accountID_, ctx_.tx.getSeqValue());
auto const slep = std::make_shared<SLE>(escrowKeylet);
EscrowEntry<ApplyView> slep{escrowKeylet, ctx_.view()};
slep.newSLE();
(*slep)[sfAmount] = amount;
(*slep)[sfAccount] = accountID_;
(*slep)[~sfCondition] = ctx_.tx[~sfCondition];
@@ -481,7 +484,7 @@ EscrowCreate::doApply()
(*slep)[sfTransferRate] = xferRate.value;
}
ctx_.view().insert(slep);
slep.insert();
// Add escrow to sender's owner directory
{
@@ -535,8 +538,8 @@ EscrowCreate::doApply()
}
// increment owner count
adjustOwnerCount(ctx_.view(), sle, 1, ctx_.journal);
ctx_.view().update(sle);
adjustOwnerCount(ctx_.view(), sle.mutableSle(), 1, ctx_.journal);
sle.update();
return tesSUCCESS;
}

View File

@@ -14,6 +14,7 @@
#include <xrpl/ledger/helpers/EscrowHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Concepts.h>
@@ -173,7 +174,7 @@ escrowFinishPreclaimHelper<MPTIssue>(
// If the mpt does not exist, return tecOBJECT_NOT_FOUND
auto const issuanceKey = keylet::mptokenIssuance(amount.get<MPTIssue>().getMptID());
auto const sleIssuance = ctx.view.read(issuanceKey);
MPTokenIssuanceEntry<ReadView> sleIssuance{issuanceKey, ctx.view};
if (!sleIssuance)
return tecOBJECT_NOT_FOUND;
@@ -204,7 +205,7 @@ EscrowFinish::preclaim(PreclaimContext const& ctx)
if (ctx.view.rules().enabled(featureTokenEscrow))
{
auto const k = keylet::escrow(ctx.tx[sfOwner], ctx.tx[sfOfferSequence]);
auto const slep = ctx.view.read(k);
EscrowEntry<ReadView> slep{k, ctx.view};
if (!slep)
return tecNO_TARGET;
@@ -229,7 +230,7 @@ TER
EscrowFinish::doApply()
{
auto const k = keylet::escrow(ctx_.tx[sfOwner], ctx_.tx[sfOfferSequence]);
auto const slep = ctx_.view().peek(k);
EscrowEntry<ApplyView> slep{k, ctx_.view()};
if (!slep)
{
if (ctx_.view().rules().enabled(featureTokenEscrow))
@@ -305,12 +306,12 @@ EscrowFinish::doApply()
// NOTE: Escrow payments cannot be used to fund accounts.
AccountID const destID = (*slep)[sfDestination];
auto const sled = ctx_.view().peek(keylet::account(destID));
AccountRootEntry<ApplyView> sled{keylet::account(destID), ctx_.view()};
if (!sled)
return tecNO_DST;
if (auto err =
verifyDepositPreauth(ctx_.tx, ctx_.view(), accountID_, destID, sled, ctx_.journal);
if (auto err = verifyDepositPreauth(
ctx_.tx, ctx_.view(), accountID_, destID, sled.sle(), ctx_.journal);
!isTesSuccess(err))
return err;
@@ -361,7 +362,7 @@ EscrowFinish::doApply()
return escrowUnlockApplyHelper<T>(
ctx_.view(),
lockedRate,
sled,
sled.mutableSle(),
preFeeBalance_,
amount,
issuer,
@@ -387,15 +388,15 @@ EscrowFinish::doApply()
}
}
ctx_.view().update(sled);
sled.update();
// Adjust source owner count
auto const sle = ctx_.view().peek(keylet::account(account));
adjustOwnerCount(ctx_.view(), sle, -1, ctx_.journal);
ctx_.view().update(sle);
AccountRootEntry<ApplyView> sle{keylet::account(account), ctx_.view()};
adjustOwnerCount(ctx_.view(), sle.mutableSle(), -1, ctx_.journal);
sle.update();
// Remove escrow from ledger
ctx_.view().erase(slep);
slep.erase();
return tesSUCCESS;
}

View File

@@ -54,16 +54,16 @@ TER
NFTokenAcceptOffer::preclaim(PreclaimContext const& ctx)
{
auto const checkOffer =
[&ctx](std::optional<uint256> id) -> std::pair<SLE::const_pointer, TER> {
[&ctx](std::optional<uint256> id) -> std::pair<NFTokenOfferEntry<ReadView>, TER> {
if (id)
{
if (id->isZero())
return {nullptr, tecOBJECT_NOT_FOUND};
return {NFTokenOfferEntry<ReadView>{nullptr, ctx.view}, tecOBJECT_NOT_FOUND};
auto offerSLE = ctx.view.read(keylet::nftokenOffer(*id));
NFTokenOfferEntry<ReadView> offerSLE{keylet::nftokenOffer(*id), ctx.view};
if (!offerSLE)
return {nullptr, tecOBJECT_NOT_FOUND};
return {NFTokenOfferEntry<ReadView>{nullptr, ctx.view}, tecOBJECT_NOT_FOUND};
if (hasExpired(ctx.view, (*offerSLE)[~sfExpiration]))
{
@@ -71,16 +71,16 @@ NFTokenAcceptOffer::preclaim(PreclaimContext const& ctx)
// leaving them on ledger forever. After the amendment, we allow expired offers to
// reach doApply() where they get deleted and tecEXPIRED is returned.
if (!ctx.view.rules().enabled(fixCleanup3_1_3))
return {nullptr, tecEXPIRED};
return {NFTokenOfferEntry<ReadView>{nullptr, ctx.view}, tecEXPIRED};
// Amendment enabled: return the expired offer to be handled in doApply.
}
if ((*offerSLE)[sfAmount].negative())
return {nullptr, temBAD_OFFER};
return {NFTokenOfferEntry<ReadView>{nullptr, ctx.view}, temBAD_OFFER};
return {std::move(offerSLE), tesSUCCESS};
}
return {nullptr, tesSUCCESS};
return {NFTokenOfferEntry<ReadView>{nullptr, ctx.view}, tesSUCCESS};
};
auto const [bo, err1] = checkOffer(ctx.tx[~sfNFTokenBuyOffer]);
@@ -396,7 +396,7 @@ NFTokenAcceptOffer::transferNFToken(
}
TER
NFTokenAcceptOffer::acceptOffer(SLE::ref offer)
NFTokenAcceptOffer::acceptOffer(NFTokenOfferEntry<ApplyView> const& offer)
{
bool const isSell = offer->isFlag(lsfSellNFToken);
AccountID const owner = (*offer)[sfOwner];
@@ -434,10 +434,9 @@ TER
NFTokenAcceptOffer::doApply()
{
auto const loadToken = [this](std::optional<uint256> const& id) {
SLE::pointer sle;
if (id)
sle = view().peek(keylet::nftokenOffer(*id));
return sle;
return NFTokenOfferEntry<ApplyView>{keylet::nftokenOffer(*id), view()};
return NFTokenOfferEntry<ApplyView>{SLE::pointer{}, view()};
};
auto bo = loadToken(ctx_.tx[~sfNFTokenBuyOffer]);
@@ -449,11 +448,12 @@ NFTokenAcceptOffer::doApply()
{
bool foundExpired = false;
auto const deleteOfferIfExpired = [this, &foundExpired](SLE::ref offer) -> TER {
auto const deleteOfferIfExpired =
[this, &foundExpired](NFTokenOfferEntry<ApplyView>& offer) -> TER {
if (offer && hasExpired(view(), (*offer)[~sfExpiration]))
{
JLOG(j_.trace()) << "Offer is expired, deleting: " << offer->key();
if (!nft::deleteTokenOffer(view(), offer))
if (!nft::deleteTokenOffer(view(), offer.mutableSle()))
{
// LCOV_EXCL_START
JLOG(j_.fatal())
@@ -476,7 +476,7 @@ NFTokenAcceptOffer::doApply()
return tecEXPIRED;
}
if (bo && !nft::deleteTokenOffer(view(), bo))
if (bo && !nft::deleteTokenOffer(view(), bo.mutableSle()))
{
// LCOV_EXCL_START
JLOG(j_.fatal()) << "Unable to delete buy offer '" << to_string(bo->key()) << "': ignoring";
@@ -484,7 +484,7 @@ NFTokenAcceptOffer::doApply()
// LCOV_EXCL_STOP
}
if (so && !nft::deleteTokenOffer(view(), so))
if (so && !nft::deleteTokenOffer(view(), so.mutableSle()))
{
// LCOV_EXCL_START
JLOG(j_.fatal()) << "Unable to delete sell offer '" << to_string(so->key())

View File

@@ -4,6 +4,7 @@
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/SField.h>
@@ -64,13 +65,13 @@ OracleDelete::deleteOracle(
// LCOV_EXCL_STOP
}
auto const sleOwner = view.peek(keylet::account(account));
AccountRootEntry<ApplyView> sleOwner{keylet::account(account), view};
if (!sleOwner)
return tecINTERNAL; // LCOV_EXCL_LINE
auto const count = sle->getFieldArray(sfPriceDataSeries).size() > 5 ? -2 : -1;
adjustOwnerCount(view, sleOwner, count, j);
adjustOwnerCount(view, sleOwner.mutableSle(), count, j);
view.erase(sle);
@@ -80,8 +81,9 @@ OracleDelete::deleteOracle(
TER
OracleDelete::doApply()
{
if (auto sle = ctx_.view().peek(keylet::oracle(accountID_, ctx_.tx[sfOracleDocumentID])))
return deleteOracle(ctx_.view(), sle, accountID_, j_);
if (OracleEntry<ApplyView> sle{
keylet::oracle(accountID_, ctx_.tx[sfOracleDocumentID]), ctx_.view()})
return deleteOracle(ctx_.view(), sle.mutableSle(), accountID_, j_);
return tecINTERNAL; // LCOV_EXCL_LINE
}

View File

@@ -4,6 +4,7 @@
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/InnerObjectFormats.h>
@@ -61,7 +62,7 @@ OracleSet::preflight(PreflightContext const& ctx)
TER
OracleSet::preclaim(PreclaimContext const& ctx)
{
auto const sleSetter = ctx.view.read(keylet::account(ctx.tx.getAccountID(sfAccount)));
AccountRootEntry<ReadView> sleSetter{keylet::account(ctx.tx.getAccountID(sfAccount)), ctx.view};
if (!sleSetter)
return terNO_ACCOUNT; // LCOV_EXCL_LINE
@@ -80,8 +81,8 @@ OracleSet::preclaim(PreclaimContext const& ctx)
lastUpdateTimeEpoch > (closeTime + kMaxLastUpdateTimeDelta))
return tecINVALID_UPDATE_TIME;
auto const sle =
ctx.view.read(keylet::oracle(ctx.tx.getAccountID(sfAccount), ctx.tx[sfOracleDocumentID]));
OracleEntry<ReadView> sle{
keylet::oracle(ctx.tx.getAccountID(sfAccount), ctx.tx[sfOracleDocumentID]), ctx.view};
// token pairs to add/update
std::set<std::pair<Currency, Currency>> pairs;
@@ -181,9 +182,9 @@ OracleSet::preclaim(PreclaimContext const& ctx)
static bool
adjustOwnerCount(ApplyContext& ctx, int count)
{
if (auto const sleAccount = ctx.view().peek(keylet::account(ctx.tx[sfAccount])))
if (AccountRootEntry<ApplyView> sleAccount{keylet::account(ctx.tx[sfAccount]), ctx.view()})
{
adjustOwnerCount(ctx.view(), sleAccount, count, ctx.journal);
adjustOwnerCount(ctx.view(), sleAccount.mutableSle(), count, ctx.journal);
return true;
}
@@ -212,7 +213,8 @@ OracleSet::doApply()
priceData.setFieldU8(sfScale, entry.getFieldU8(sfScale));
};
if (auto sle = ctx_.view().peek(oracleID))
OracleEntry<ApplyView> sle{oracleID, ctx_.view()};
if (sle)
{
// update
// the token pair that doesn't have their price updated will not
@@ -271,13 +273,13 @@ OracleSet::doApply()
if (adjust != 0 && !adjustOwnerCount(ctx_, adjust))
return tefINTERNAL; // LCOV_EXCL_LINE
ctx_.view().update(sle);
sle.update();
}
else
{
// create
sle = std::make_shared<SLE>(oracleID);
sle.newSLE();
sle->setAccountID(sfOwner, ctx_.tx.getAccountID(sfAccount));
if (ctx_.view().rules().enabled(fixIncludeKeyletFields))
{
@@ -321,7 +323,7 @@ OracleSet::doApply()
if (!adjustOwnerCount(ctx_, count))
return tefINTERNAL; // LCOV_EXCL_LINE
ctx_.view().insert(sle);
sle.insert();
}
return tesSUCCESS;

View File

@@ -10,6 +10,7 @@
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/PermissionedDEXHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Asset.h>
@@ -460,24 +461,24 @@ Payment::doApply()
// Open a ledger for editing.
auto const k = keylet::account(dstAccountID);
SLE::pointer sleDst = view().peek(k);
AccountRootEntry<ApplyView> sleDst{k, view()};
if (!sleDst)
{
// Create the account.
sleDst = std::make_shared<SLE>(k);
sleDst.newSLE();
sleDst->setAccountID(sfAccount, dstAccountID);
sleDst->setFieldU32(sfSequence, view().seq());
sleDst->setFieldAmount(sfBalance, XRPAmount(beast::kZero));
view().insert(sleDst);
sleDst.insert();
}
else
{
// Tell the engine that we are intending to change the destination
// account. The source account gets always charged a fee so it's always
// marked as modified.
view().update(sleDst);
sleDst.update();
}
bool const mpTokensV2 = view().rules().enabled(featureMPTokensV2);
@@ -496,7 +497,7 @@ Payment::doApply()
// 2. If Account is deposit preauthorized by destination.
if (auto err = verifyDepositPreauth(
ctx_.tx, ctx_.view(), accountID_, dstAccountID, sleDst, ctx_.journal);
ctx_.tx, ctx_.view(), accountID_, dstAccountID, sleDst.sle(), ctx_.journal);
!isTesSuccess(err))
return err;
@@ -566,7 +567,7 @@ Payment::doApply()
return ter;
if (auto err = verifyDepositPreauth(
ctx_.tx, ctx_.view(), accountID_, dstAccountID, sleDst, ctx_.journal);
ctx_.tx, ctx_.view(), accountID_, dstAccountID, sleDst.sle(), ctx_.journal);
!isTesSuccess(err))
return err;
@@ -669,7 +670,7 @@ Payment::doApply()
// transaction types. Note, this is not amendment-gated because all writes
// to pseudo-account discriminator fields **are** amendment gated, hence the
// behaviour of this check will always match the active amendments.
if (isPseudoAccount(sleDst))
if (isPseudoAccount(sleDst.sle()))
return tecNO_PERMISSION;
// The source account does have enough money. Make sure the
@@ -699,7 +700,7 @@ Payment::doApply()
if (dstAmount > dstReserve || sleDst->getFieldAmount(sfBalance) > dstReserve)
{
if (auto err = verifyDepositPreauth(
ctx_.tx, ctx_.view(), accountID_, dstAccountID, sleDst, ctx_.journal);
ctx_.tx, ctx_.view(), accountID_, dstAccountID, sleDst.sle(), ctx_.journal);
!isTesSuccess(err))
return err;
}

View File

@@ -110,7 +110,7 @@ TER
PaymentChannelClaim::doApply()
{
Keylet const k(ltPAYCHAN, ctx_.tx[sfChannel]);
auto const slep = ctx_.view().peek(k);
PayChannelEntry<ApplyView> slep{k, ctx_.view()};
if (!slep)
return tecNO_TARGET;
@@ -159,12 +159,12 @@ PaymentChannelClaim::doApply()
return tecUNFUNDED_PAYMENT;
}
auto const sled = ctx_.view().peek(keylet::account(dst));
AccountRootEntry<ApplyView> sled{dst, ctx_.view()};
if (!sled)
return tecNO_DST;
if (auto err =
verifyDepositPreauth(ctx_.tx, ctx_.view(), txAccount, dst, sled, ctx_.journal);
if (auto err = verifyDepositPreauth(
ctx_.tx, ctx_.view(), txAccount, dst, sled.sle(), ctx_.journal);
!isTesSuccess(err))
return err;
@@ -173,8 +173,8 @@ PaymentChannelClaim::doApply()
XRPL_ASSERT(
reqDelta >= beast::kZero, "xrpl::PaymentChannelClaim::doApply : minimum balance delta");
(*sled)[sfBalance] = (*sled)[sfBalance] + reqDelta;
ctx_.view().update(sled);
ctx_.view().update(slep);
sled.update();
slep.update();
}
if (ctx_.tx.isFlag(tfRenew))
@@ -182,7 +182,7 @@ PaymentChannelClaim::doApply()
if (src != txAccount)
return tecNO_PERMISSION;
(*slep)[~sfExpiration] = std::nullopt;
ctx_.view().update(slep);
slep.update();
}
if (ctx_.tx.isFlag(tfClose))
@@ -199,7 +199,7 @@ PaymentChannelClaim::doApply()
if (!curExpiration || *curExpiration > settleExpiration)
{
(*slep)[~sfExpiration] = settleExpiration;
ctx_.view().update(slep);
slep.update();
}
}

View File

@@ -43,7 +43,7 @@ TER
PaymentChannelFund::doApply()
{
Keylet const k(ltPAYCHAN, ctx_.tx[sfChannel]);
auto const slep = ctx_.view().peek(k);
PayChannelEntry<ApplyView> slep{k, ctx_.view()};
if (!slep)
return tecNO_ENTRY;
@@ -78,10 +78,10 @@ PaymentChannelFund::doApply()
: TER{temBAD_EXPIRATION};
}
(*slep)[~sfExpiration] = *newExpiration;
ctx_.view().update(slep);
slep.update();
}
auto const sle = ctx_.view().peek(keylet::account(txAccount));
AccountRootEntry<ApplyView> sle{txAccount, ctx_.view()};
if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -104,10 +104,10 @@ PaymentChannelFund::doApply()
}
(*slep)[sfAmount] = (*slep)[sfAmount] + ctx_.tx[sfAmount];
ctx_.view().update(slep);
slep.update();
(*sle)[sfBalance] = (*sle)[sfBalance] - ctx_.tx[sfAmount];
ctx_.view().update(sle);
sle.update();
return tesSUCCESS;
}

View File

@@ -4,6 +4,7 @@
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STLedgerEntry.h>
@@ -28,7 +29,7 @@ TER
PermissionedDomainDelete::preclaim(PreclaimContext const& ctx)
{
auto const domain = ctx.tx.getFieldH256(sfDomainID);
auto const sleDomain = ctx.view.read(keylet::permissionedDomain(domain));
PermissionedDomainEntry<ReadView> sleDomain{keylet::permissionedDomain(domain), ctx.view};
if (!sleDomain)
return tecNO_ENTRY;
@@ -50,7 +51,8 @@ PermissionedDomainDelete::doApply()
ctx_.tx.isFieldPresent(sfDomainID),
"xrpl::PermissionedDomainDelete::doApply : required field present");
auto const slePd = view().peek(keylet::permissionedDomain(ctx_.tx.at(sfDomainID)));
PermissionedDomainEntry<ApplyView> slePd{
keylet::permissionedDomain(ctx_.tx.at(sfDomainID)), view()};
auto const page = (*slePd)[sfOwnerNode];
if (!view().dirRemove(keylet::ownerDir(accountID_), page, slePd->key(), true))
@@ -61,12 +63,12 @@ PermissionedDomainDelete::doApply()
// LCOV_EXCL_STOP
}
auto const ownerSle = view().peek(keylet::account(accountID_));
AccountRootEntry<ApplyView> ownerSle{keylet::account(accountID_), view()};
XRPL_ASSERT(
ownerSle && ownerSle->getFieldU32(sfOwnerCount) > 0,
"xrpl::PermissionedDomainDelete::doApply : nonzero owner count");
adjustOwnerCount(view(), ownerSle, -1, ctx_.journal);
view().erase(slePd);
adjustOwnerCount(view(), ownerSle.mutableSle(), -1, ctx_.journal);
slePd.erase();
return tesSUCCESS;
}

View File

@@ -5,6 +5,7 @@
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Keylet.h>
@@ -62,8 +63,8 @@ PermissionedDomainSet::preclaim(PreclaimContext const& ctx)
if (ctx.tx.isFieldPresent(sfDomainID))
{
auto const sleDomain =
ctx.view.read(keylet::permissionedDomain(ctx.tx.getFieldH256(sfDomainID)));
PermissionedDomainEntry<ReadView> sleDomain{
keylet::permissionedDomain(ctx.tx.getFieldH256(sfDomainID)), ctx.view};
if (!sleDomain)
return tecNO_ENTRY;
if (sleDomain->getAccountID(sfOwner) != account)
@@ -77,7 +78,7 @@ PermissionedDomainSet::preclaim(PreclaimContext const& ctx)
TER
PermissionedDomainSet::doApply()
{
auto const ownerSle = view().peek(keylet::account(accountID_));
AccountRootEntry<ApplyView> ownerSle{keylet::account(accountID_), view()};
if (!ownerSle)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -95,11 +96,12 @@ PermissionedDomainSet::doApply()
if (ctx_.tx.isFieldPresent(sfDomainID))
{
// Modify existing permissioned domain.
auto slePd = view().peek(keylet::permissionedDomain(ctx_.tx.getFieldH256(sfDomainID)));
PermissionedDomainEntry<ApplyView> slePd{
keylet::permissionedDomain(ctx_.tx.getFieldH256(sfDomainID)), view()};
if (!slePd)
return tefINTERNAL; // LCOV_EXCL_LINE
slePd->peekFieldArray(sfAcceptedCredentials) = std::move(sortedLE);
view().update(slePd);
slePd.update();
}
else
{
@@ -113,7 +115,8 @@ PermissionedDomainSet::doApply()
bool const fixEnabled = view().rules().enabled(fixCleanup3_1_3);
auto const seq = fixEnabled ? ctx_.tx.getSeqValue() : ctx_.tx.getFieldU32(sfSequence);
Keylet const pdKeylet = keylet::permissionedDomain(accountID_, seq);
auto slePd = std::make_shared<SLE>(pdKeylet);
PermissionedDomainEntry<ApplyView> slePd{pdKeylet, view()};
slePd.newSLE();
slePd->setAccountID(sfOwner, accountID_);
slePd->setFieldU32(sfSequence, seq);
@@ -125,8 +128,8 @@ PermissionedDomainSet::doApply()
slePd->setFieldU64(sfOwnerNode, *page);
// If we succeeded, the new entry counts against the creator's reserve.
adjustOwnerCount(view(), ownerSle, 1, ctx_.journal);
view().insert(slePd);
adjustOwnerCount(view(), ownerSle.mutableSle(), 1, ctx_.journal);
slePd.insert();
}
return tesSUCCESS;

View File

@@ -8,6 +8,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/AmendmentTable.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Protocol.h>
@@ -162,14 +163,12 @@ Change::applyAmendment()
{
uint256 const amendment(ctx_.tx.getFieldH256(sfAmendment));
auto const k = keylet::amendments();
SLE::pointer amendmentObject = view().peek(k);
AmendmentsEntry<ApplyView> amendmentObject{view()};
if (!amendmentObject)
{
amendmentObject = std::make_shared<SLE>(k);
view().insert(amendmentObject);
amendmentObject.newSLE();
amendmentObject.insert();
}
STVector256 amendments = amendmentObject->getFieldV256(sfAmendments);
@@ -246,7 +245,7 @@ Change::applyAmendment()
amendmentObject->setFieldArray(sfMajorities, newMajorities);
}
view().update(amendmentObject);
amendmentObject.update();
return tesSUCCESS;
}
@@ -254,16 +253,14 @@ Change::applyAmendment()
TER
Change::applyFee()
{
auto const k = keylet::feeSettings();
SLE::pointer feeObject = view().peek(k);
FeeSettingsEntry<ApplyView> feeObject{view()};
if (!feeObject)
{
feeObject = std::make_shared<SLE>(k);
view().insert(feeObject);
feeObject.newSLE();
feeObject.insert();
}
auto set = [](SLE::pointer& feeObject, STTx const& tx, auto const& field) {
auto set = [](auto& feeObject, STTx const& tx, auto const& field) {
feeObject->at(field) = tx[field];
};
if (view().rules().enabled(featureXRPFees))
@@ -285,7 +282,7 @@ Change::applyFee()
set(feeObject, ctx_.tx, sfReserveIncrement);
}
view().update(feeObject);
feeObject.update();
JLOG(j_.warn()) << "Fees have been changed";
return tesSUCCESS;
@@ -326,12 +323,11 @@ Change::applyUNLModify()
JLOG(j_.info()) << "N-UNL: applyUNLModify, " << (disabling ? "ToDisable" : "ToReEnable")
<< " seq=" << seq << " validator data:" << strHex(validator);
auto const k = keylet::negativeUNL();
SLE::pointer negUnlObject = view().peek(k);
NegativeUNLEntry<ApplyView> negUnlObject{view()};
if (!negUnlObject)
{
negUnlObject = std::make_shared<SLE>(k);
view().insert(negUnlObject);
negUnlObject.newSLE();
negUnlObject.insert();
}
bool const found = [&] {
@@ -404,7 +400,7 @@ Change::applyUNLModify()
negUnlObject->setFieldVL(sfValidatorToReEnable, validator);
}
view().update(negUnlObject);
negUnlObject.update();
return tesSUCCESS;
}

View File

@@ -6,6 +6,7 @@
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Keylet.h>
#include <xrpl/protocol/SField.h>
@@ -67,7 +68,7 @@ TicketCreate::preclaim(PreclaimContext const& ctx)
TER
TicketCreate::doApply()
{
SLE::pointer const sleAccountRoot = view().peek(keylet::account(accountID_));
AccountRootEntry<ApplyView> sleAccountRoot{keylet::account(accountID_), view()};
if (!sleAccountRoot)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -101,11 +102,12 @@ TicketCreate::doApply()
{
std::uint32_t const curTicketSeq = firstTicketSeq + i;
Keylet const ticketKeylet = keylet::ticket(accountID_, curTicketSeq);
SLE::pointer const sleTicket = std::make_shared<SLE>(ticketKeylet);
TicketEntry<ApplyView> sleTicket{ticketKeylet, view()};
sleTicket.newSLE();
sleTicket->setAccountID(sfAccount, accountID_);
sleTicket->setFieldU32(sfTicketSequence, curTicketSeq);
view().insert(sleTicket);
sleTicket.insert();
auto const page = view().dirInsert(
keylet::ownerDir(accountID_), ticketKeylet, describeOwnerDir(accountID_));
@@ -125,7 +127,7 @@ TicketCreate::doApply()
sleAccountRoot->setFieldU32(sfTicketCount, oldTicketCount + ticketCount);
// Every added Ticket counts against the creator's reserve.
adjustOwnerCount(view(), sleAccountRoot, ticketCount, viewJ);
adjustOwnerCount(view(), sleAccountRoot.mutableSle(), ticketCount, viewJ);
// TicketCreate is the only transaction that can cause an account root's
// Sequence field to increase by more than one. October 2018.

View File

@@ -3,6 +3,7 @@
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
@@ -46,8 +47,8 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx)
// `holderID` is NOT used
if (!holderID)
{
SLE::const_pointer const sleMpt =
ctx.view.read(keylet::mptoken(ctx.tx[sfMPTokenIssuanceID], accountID));
MPTokenEntry<ReadView> const sleMpt{
keylet::mptoken(ctx.tx[sfMPTokenIssuanceID], accountID), ctx.view};
// There is an edge case where all holders have zero balance, issuance
// is legally destroyed, then outstanding MPT(s) are deleted afterwards.

View File

@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -301,16 +302,10 @@ MPTokenIssuanceSet::doApply()
auto const mptIssuanceID = ctx_.tx[sfMPTokenIssuanceID];
auto const holderID = ctx_.tx[~sfHolder];
auto const domainID = ctx_.tx[~sfDomainID];
SLE::pointer sle;
if (holderID)
{
sle = view().peek(keylet::mptoken(mptIssuanceID, *holderID));
}
else
{
sle = view().peek(keylet::mptokenIssuance(mptIssuanceID));
}
WritableSLE sle{
holderID ? keylet::mptoken(mptIssuanceID, *holderID)
: keylet::mptokenIssuance(mptIssuanceID),
view()};
if (!sle)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -410,7 +405,7 @@ MPTokenIssuanceSet::doApply()
sle->setFieldVL(sfAuditorEncryptionKey, *pubKey);
}
view().update(sle);
sle.update();
return tesSUCCESS;
}

View File

@@ -7,6 +7,7 @@
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
@@ -293,7 +294,7 @@ TrustSet::doApply()
// true, if current is high account.
bool const bHigh = accountID_ > uDstAccountID;
auto const sle = view().peek(keylet::account(accountID_));
AccountRootEntry<ApplyView> sle{keylet::account(accountID_), view()};
if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -337,7 +338,7 @@ TrustSet::doApply()
auto viewJ = ctx_.registry.get().getJournal("View");
SLE::pointer const sleDst = view().peek(keylet::account(uDstAccountID));
AccountRootEntry<ApplyView> sleDst{keylet::account(uDstAccountID), view()};
if (!sleDst)
{
@@ -348,8 +349,8 @@ TrustSet::doApply()
STAmount saLimitAllow = saLimitAmount;
saLimitAllow.get<Issue>().account = accountID_;
SLE::pointer const sleRippleState =
view().peek(keylet::trustLine(accountID_, uDstAccountID, currency));
RippleStateEntry<ApplyView> sleRippleState{
keylet::trustLine(accountID_, uDstAccountID, currency), view()};
if (sleRippleState)
{
@@ -363,8 +364,8 @@ TrustSet::doApply()
std::uint32_t uHighQualityOut = 0;
auto const& uLowAccountID = !bHigh ? accountID_ : uDstAccountID;
auto const& uHighAccountID = bHigh ? accountID_ : uDstAccountID;
SLE::ref sleLowAccount = !bHigh ? sle : sleDst;
SLE::ref sleHighAccount = bHigh ? sle : sleDst;
AccountRootEntry<ApplyView>& sleLowAccount = !bHigh ? sle : sleDst;
AccountRootEntry<ApplyView>& sleHighAccount = bHigh ? sle : sleDst;
//
// Balances
@@ -513,7 +514,7 @@ TrustSet::doApply()
if (bLowReserveSet && !bLowReserved)
{
// Set reserve for low account.
adjustOwnerCount(view(), sleLowAccount, 1, viewJ);
adjustOwnerCount(view(), sleLowAccount.mutableSle(), 1, viewJ);
uFlagsOut |= lsfLowReserve;
if (!bHigh)
@@ -523,14 +524,14 @@ TrustSet::doApply()
if (bLowReserveClear && bLowReserved)
{
// Clear reserve for low account.
adjustOwnerCount(view(), sleLowAccount, -1, viewJ);
adjustOwnerCount(view(), sleLowAccount.mutableSle(), -1, viewJ);
uFlagsOut &= ~lsfLowReserve;
}
if (bHighReserveSet && !bHighReserved)
{
// Set reserve for high account.
adjustOwnerCount(view(), sleHighAccount, 1, viewJ);
adjustOwnerCount(view(), sleHighAccount.mutableSle(), 1, viewJ);
uFlagsOut |= lsfHighReserve;
if (bHigh)
@@ -540,7 +541,7 @@ TrustSet::doApply()
if (bHighReserveClear && bHighReserved)
{
// Clear reserve for high account.
adjustOwnerCount(view(), sleHighAccount, -1, viewJ);
adjustOwnerCount(view(), sleHighAccount.mutableSle(), -1, viewJ);
uFlagsOut &= ~lsfHighReserve;
}
@@ -551,7 +552,8 @@ TrustSet::doApply()
{
// Delete.
terResult = trustDelete(view(), sleRippleState, uLowAccountID, uHighAccountID, viewJ);
terResult = trustDelete(
view(), sleRippleState.mutableSle(), uLowAccountID, uHighAccountID, viewJ);
}
// Reserve is not scaled by load.
else if (bReserveIncrease && preFeeBalance_ < reserveCreate)
@@ -565,7 +567,7 @@ TrustSet::doApply()
}
else
{
view().update(sleRippleState);
sleRippleState.update();
JLOG(j_.trace()) << "Modify ripple line";
}
@@ -608,7 +610,7 @@ TrustSet::doApply()
accountID_,
uDstAccountID,
k.key,
sle,
sle.mutableSle(),
bSetAuth,
bSetNoRipple && !bClearNoRipple,
bSetFreeze && !bClearFreeze,

View File

@@ -60,7 +60,7 @@ VaultClawback::preflight(PreflightContext const& ctx)
[[nodiscard]] STAmount
clawbackAmount(
SLE::const_ref vault,
VaultEntry<ReadView> const& vault,
std::optional<STAmount> const& maybeAmount,
AccountID const& account)
{
@@ -77,7 +77,7 @@ clawbackAmount(
TER
VaultClawback::preclaim(PreclaimContext const& ctx)
{
auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
VaultEntry<ReadView> vault{keylet::vault(ctx.tx[sfVaultID]), ctx.view};
if (!vault)
return tecNO_ENTRY;
@@ -86,7 +86,8 @@ VaultClawback::preclaim(PreclaimContext const& ctx)
auto const holder = ctx.tx[sfHolder];
auto const maybeAmount = ctx.tx[~sfAmount];
auto const mptIssuanceID = vault->at(sfShareMPTID);
auto const sleShareIssuance = ctx.view.read(keylet::mptokenIssuance(mptIssuanceID));
MPTokenIssuanceEntry<ReadView> sleShareIssuance{
keylet::mptokenIssuance(mptIssuanceID), ctx.view};
if (!sleShareIssuance)
{
// LCOV_EXCL_START
@@ -180,8 +181,9 @@ VaultClawback::preclaim(PreclaimContext const& ctx)
return vaultAsset.visit(
[&](MPTIssue const& issue) -> TER {
auto const mptIssue = ctx.view.read(keylet::mptokenIssuance(issue.getMptID()));
if (mptIssue == nullptr)
MPTokenIssuanceEntry<ReadView> mptIssue{
keylet::mptokenIssuance(issue.getMptID()), ctx.view};
if (!mptIssue)
return tecOBJECT_NOT_FOUND;
if (!mptIssue->isFlag(lsfMPTCanClawback))
@@ -194,7 +196,7 @@ VaultClawback::preclaim(PreclaimContext const& ctx)
return tesSUCCESS;
},
[&](Issue const&) -> TER {
auto const issuerSle = ctx.view.read(keylet::account(account));
AccountRootEntry<ReadView> issuerSle{keylet::account(account), ctx.view};
if (!issuerSle)
{
// LCOV_EXCL_START
@@ -220,8 +222,8 @@ VaultClawback::preclaim(PreclaimContext const& ctx)
std::expected<std::pair<STAmount, STAmount>, TER>
VaultClawback::assetsToClawback(
SLE::ref vault,
SLE::const_ref sleShareIssuance,
VaultEntry<ApplyView>& vault,
MPTokenIssuanceEntry<ReadView> const& sleShareIssuance,
AccountID const& holder,
STAmount const& clawbackAmount)
{
@@ -332,12 +334,12 @@ TER
VaultClawback::doApply()
{
auto const& tx = ctx_.tx;
auto const vault = view().peek(keylet::vault(tx[sfVaultID]));
VaultEntry<ApplyView> vault{keylet::vault(tx[sfVaultID]), view()};
if (!vault)
return tefINTERNAL; // LCOV_EXCL_LINE
auto const mptIssuanceID = *vault->at(sfShareMPTID);
auto const sleIssuance = view().read(keylet::mptokenIssuance(mptIssuanceID));
MPTokenIssuanceEntry<ReadView> sleIssuance{keylet::mptokenIssuance(mptIssuanceID), view()};
if (!sleIssuance)
{
// LCOV_EXCL_START
@@ -385,7 +387,7 @@ VaultClawback::doApply()
assetsTotal -= assetsRecovered;
assetsAvailable -= assetsRecovered;
view().update(vault);
vault.update();
auto const& vaultAccount = vault->at(sfAccount);
// Transfer shares from holder to vault.

View File

@@ -7,6 +7,7 @@
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Asset.h>
@@ -147,8 +148,8 @@ VaultCreate::doApply()
auto const& tx = ctx_.tx;
auto const sequence = tx.getSeqValue();
auto const owner = view().peek(keylet::account(accountID_));
if (owner == nullptr)
AccountRootEntry<ApplyView> owner{keylet::account(accountID_), view()};
if (!owner)
return tefINTERNAL; // LCOV_EXCL_LINE
auto vault = std::make_shared<SLE>(keylet::vault(accountID_, sequence));
@@ -156,7 +157,7 @@ VaultCreate::doApply()
if (auto ter = dirLink(view(), accountID_, vault))
return ter;
// We will create Vault and PseudoAccount, hence increase OwnerCount by 2
adjustOwnerCount(view(), owner, 2, j_);
adjustOwnerCount(view(), owner.mutableSle(), 2, j_);
auto const ownerCount = owner->at(sfOwnerCount);
if (preFeeBalance_ < view().fees().accountReserve(ownerCount))
return tecINSUFFICIENT_RESERVE;

View File

@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
@@ -42,7 +43,7 @@ VaultDelete::preflight(PreflightContext const& ctx)
TER
VaultDelete::preclaim(PreclaimContext const& ctx)
{
auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
VaultEntry<ReadView> vault{keylet::vault(ctx.tx[sfVaultID]), ctx.view};
if (!vault)
return tecNO_ENTRY;
@@ -65,7 +66,8 @@ VaultDelete::preclaim(PreclaimContext const& ctx)
}
// Verify we can destroy MPTokenIssuance
auto const sleMPT = ctx.view.read(keylet::mptokenIssuance(vault->at(sfShareMPTID)));
MPTokenIssuanceEntry<ReadView> sleMPT{
keylet::mptokenIssuance(vault->at(sfShareMPTID)), ctx.view};
if (!sleMPT)
{
@@ -95,7 +97,7 @@ VaultDelete::preclaim(PreclaimContext const& ctx)
TER
VaultDelete::doApply()
{
auto const vault = view().peek(keylet::vault(ctx_.tx[sfVaultID]));
VaultEntry<ApplyView> vault{keylet::vault(ctx_.tx[sfVaultID]), view()};
if (!vault)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -106,7 +108,7 @@ VaultDelete::doApply()
return ter;
auto const& pseudoID = vault->at(sfAccount);
auto const pseudoAcct = view().peek(keylet::account(pseudoID));
AccountRootEntry<ApplyView> pseudoAcct{keylet::account(pseudoID), view()};
if (!pseudoAcct)
{
// LCOV_EXCL_START
@@ -118,7 +120,7 @@ VaultDelete::doApply()
// Destroy the share issuance. Do not use MPTokenIssuanceDestroy for this,
// no special logic needed. First run few checks, duplicated from preclaim.
auto const shareMPTID = *vault->at(sfShareMPTID);
auto const mpt = view().peek(keylet::mptokenIssuance(shareMPTID));
MPTokenIssuanceEntry<ApplyView> mpt{keylet::mptokenIssuance(shareMPTID), view()};
if (!mpt)
{
// LCOV_EXCL_START
@@ -128,7 +130,7 @@ VaultDelete::doApply()
}
// Try to remove MPToken for vault shares for the vault owner if it exists.
if (auto const mptoken = view().peek(keylet::mptoken(shareMPTID, accountID_)))
if (MPTokenEntry<ApplyView> mptoken{keylet::mptoken(shareMPTID, accountID_), view()})
{
if (auto const ter = removeEmptyHolding(view(), accountID_, MPTIssue(shareMPTID), j_);
!isTesSuccess(ter))
@@ -151,16 +153,16 @@ VaultDelete::doApply()
return tefBAD_LEDGER;
// LCOV_EXCL_STOP
}
adjustOwnerCount(view(), pseudoAcct, -1, j_);
adjustOwnerCount(view(), pseudoAcct.mutableSle(), -1, j_);
view().erase(mpt);
mpt.erase();
// The pseudo-account's directory should have been deleted already.
if (view().peek(keylet::ownerDir(pseudoID)))
if (DirectoryNodeEntry<ApplyView>{keylet::ownerDir(pseudoID), view()})
return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE
// Destroy the pseudo-account.
auto vaultPseudoSLE = view().peek(keylet::account(pseudoID));
AccountRootEntry<ApplyView> vaultPseudoSLE{keylet::account(pseudoID), view()};
if (!vaultPseudoSLE || vaultPseudoSLE->at(~sfVaultID) != vault->key())
return tefBAD_LEDGER; // LCOV_EXCL_LINE
@@ -188,7 +190,7 @@ VaultDelete::doApply()
// LCOV_EXCL_STOP
}
view().erase(vaultPseudoSLE);
vaultPseudoSLE.erase();
// Remove the vault from its owner's directory.
auto const ownerID = vault->at(sfOwner);
@@ -200,7 +202,7 @@ VaultDelete::doApply()
// LCOV_EXCL_STOP
}
auto const owner = view().peek(keylet::account(ownerID));
AccountRootEntry<ApplyView> owner{keylet::account(ownerID), view()};
if (!owner)
{
// LCOV_EXCL_START
@@ -210,10 +212,10 @@ VaultDelete::doApply()
}
// We are destroying Vault and PseudoAccount, hence decrease by 2
adjustOwnerCount(view(), owner, -2, j_);
adjustOwnerCount(view(), owner.mutableSle(), -2, j_);
// Destroy the vault.
view().erase(vault);
vault.erase();
return tesSUCCESS;
}

View File

@@ -29,7 +29,7 @@ namespace xrpl {
[[nodiscard]]
static STAmount
roundToVaultScale(STAmount const& amount, SLE::const_ref vault)
roundToVaultScale(STAmount const& amount, VaultEntry<ReadView> const& vault)
{
XRPL_ASSERT(vault && vault->getType() == ltVAULT, "xrpl::roundToVaultScale : valid vault sle");
XRPL_ASSERT(
@@ -66,7 +66,7 @@ VaultDeposit::preclaim(PreclaimContext const& ctx)
auto const fix320Enabled = ctx.view.rules().enabled(fixCleanup3_2_0);
auto const fix330Enabled = ctx.view.rules().enabled(fixCleanup3_3_0);
auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
VaultEntry<ReadView> vault{keylet::vault(ctx.tx[sfVaultID]), ctx.view};
if (!vault)
return tecNO_ENTRY;
@@ -93,7 +93,7 @@ VaultDeposit::preclaim(PreclaimContext const& ctx)
// LCOV_EXCL_STOP
}
auto const sleIssuance = ctx.view.read(keylet::mptokenIssuance(mptIssuanceID));
MPTokenIssuanceEntry<ReadView> sleIssuance{keylet::mptokenIssuance(mptIssuanceID), ctx.view};
if (!sleIssuance)
{
// LCOV_EXCL_START
@@ -195,7 +195,7 @@ TER
VaultDeposit::doApply()
{
bool const fix320Enabled = view().rules().enabled(fixCleanup3_2_0);
auto const vault = view().peek(keylet::vault(ctx_.tx[sfVaultID]));
VaultEntry<ApplyView> vault{keylet::vault(ctx_.tx[sfVaultID]), view()};
if (!vault)
return tefINTERNAL; // LCOV_EXCL_LINE
auto const vaultAsset = vault->at(sfAsset);
@@ -216,7 +216,7 @@ VaultDeposit::doApply()
// Make sure the depositor can hold shares.
auto const mptIssuanceID = (*vault)[sfShareMPTID];
auto const sleIssuance = view().read(keylet::mptokenIssuance(mptIssuanceID));
MPTokenIssuanceEntry<ReadView> sleIssuance{keylet::mptokenIssuance(mptIssuanceID), view()};
if (!sleIssuance)
{
// LCOV_EXCL_START
@@ -310,7 +310,7 @@ VaultDeposit::doApply()
vault->at(sfAssetsTotal) += assetsDeposited;
vault->at(sfAssetsAvailable) += assetsDeposited;
view().update(vault);
vault.update();
// A deposit must not push the vault over its limit.
auto const maximum = *vault->at(sfAssetsMaximum);

View File

@@ -2,6 +2,7 @@
#include <xrpl/basics/Log.h>
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/ledger/helpers/SLEWrappers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
@@ -63,7 +64,7 @@ VaultSet::preflight(PreflightContext const& ctx)
TER
VaultSet::preclaim(PreclaimContext const& ctx)
{
auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
VaultEntry<ReadView> vault{keylet::vault(ctx.tx[sfVaultID]), ctx.view};
if (!vault)
return tecNO_ENTRY;
@@ -75,7 +76,7 @@ VaultSet::preclaim(PreclaimContext const& ctx)
}
auto const mptIssuanceID = (*vault)[sfShareMPTID];
auto const sleIssuance = ctx.view.read(keylet::mptokenIssuance(mptIssuanceID));
MPTokenIssuanceEntry<ReadView> sleIssuance{keylet::mptokenIssuance(mptIssuanceID), ctx.view};
if (!sleIssuance)
{
// LCOV_EXCL_START
@@ -95,7 +96,8 @@ VaultSet::preclaim(PreclaimContext const& ctx)
if (*domain != beast::kZero)
{
auto const sleDomain = ctx.view.read(keylet::permissionedDomain(*domain));
PermissionedDomainEntry<ReadView> sleDomain{
keylet::permissionedDomain(*domain), ctx.view};
if (!sleDomain)
return tecOBJECT_NOT_FOUND;
}
@@ -123,14 +125,14 @@ VaultSet::doApply()
auto const& tx = ctx_.tx;
// Update existing object.
auto vault = view().peek(keylet::vault(tx[sfVaultID]));
VaultEntry<ApplyView> vault{keylet::vault(tx[sfVaultID]), view()};
if (!vault)
return tefINTERNAL; // LCOV_EXCL_LINE
auto const vaultAsset = vault->at(sfAsset);
auto const mptIssuanceID = (*vault)[sfShareMPTID];
auto const sleIssuance = view().peek(keylet::mptokenIssuance(mptIssuanceID));
MPTokenIssuanceEntry<ApplyView> sleIssuance{keylet::mptokenIssuance(mptIssuanceID), view()};
if (!sleIssuance)
{
// LCOV_EXCL_START
@@ -164,13 +166,13 @@ VaultSet::doApply()
{
sleIssuance->makeFieldAbsent(sfDomainID);
}
view().update(sleIssuance);
sleIssuance.update();
}
// Note, we must update Vault object even if only DomainID is being updated
// in Issuance object. Otherwise it's really difficult for Vault invariants
// to verify the operation.
view().update(vault);
vault.update();
associateAsset(*vault, vaultAsset);

View File

@@ -28,7 +28,10 @@
namespace xrpl {
static WaiveUnrealizedLoss
shouldWaiveWithdrawal(ReadView const& view, AccountID const& account, SLE::const_ref issuance)
shouldWaiveWithdrawal(
ReadView const& view,
AccountID const& account,
MPTokenIssuanceEntry<ReadView> const& issuance)
{
XRPL_ASSERT(
issuance && issuance->getType() == ltMPTOKEN_ISSUANCE,
@@ -69,7 +72,7 @@ VaultWithdraw::preclaim(PreclaimContext const& ctx)
auto const fix320Enabled = ctx.view.rules().enabled(fixCleanup3_2_0);
auto const fix330Enabled = ctx.view.rules().enabled(fixCleanup3_3_0);
auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
VaultEntry<ReadView> vault{keylet::vault(ctx.tx[sfVaultID]), ctx.view};
if (!vault)
return tecNO_ENTRY;
@@ -109,7 +112,7 @@ VaultWithdraw::preclaim(PreclaimContext const& ctx)
// to the equivalent asset amount before checking withdrawal
// limits. Pre-amendment the limit check was skipped for
// share-denominated withdrawals.
auto const sleIssuance = ctx.view.read(keylet::mptokenIssuance(vaultShare));
MPTokenIssuanceEntry<ReadView> sleIssuance{keylet::mptokenIssuance(vaultShare), ctx.view};
if (!sleIssuance)
{
// LCOV_EXCL_START
@@ -193,12 +196,12 @@ VaultWithdraw::preclaim(PreclaimContext const& ctx)
TER
VaultWithdraw::doApply()
{
auto const vault = view().peek(keylet::vault(ctx_.tx[sfVaultID]));
VaultEntry<ApplyView> vault{keylet::vault(ctx_.tx[sfVaultID]), view()};
if (!vault)
return tefINTERNAL; // LCOV_EXCL_LINE
auto const mptIssuanceID = *((*vault)[sfShareMPTID]);
auto const sleIssuance = view().read(keylet::mptokenIssuance(mptIssuanceID));
MPTokenIssuanceEntry<ReadView> sleIssuance{keylet::mptokenIssuance(mptIssuanceID), view()};
if (!sleIssuance)
{
// LCOV_EXCL_START
@@ -346,7 +349,7 @@ VaultWithdraw::doApply()
assetsTotal -= assetsWithdrawn;
assetsAvailable -= assetsWithdrawn;
}
view().update(vault);
vault.update();
auto const& vaultAccount = vault->at(sfAccount);
// Transfer shares from depositor to vault.

View File

@@ -1525,8 +1525,9 @@ public:
for (auto const& tc : testCases)
{
testcase("canApplyToBrokerCover: " + tc.name);
auto sle = std::make_shared<SLE>(ltLOAN_BROKER, uint256{1u});
sle->at(sfCoverAvailable) = tc.coverAvailable;
auto broker = std::make_shared<SLE>(Keylet{ltLOAN_BROKER, uint256{1u}});
broker->at(sfCoverAvailable) = tc.coverAvailable;
LoanBrokerEntry<ReadView> sle{broker, *env.current()};
BEAST_EXPECT(
canApplyToBrokerCover(*env.current(), sle, iou, tc.amount, env.journal, "test") ==
tc.expected);
@@ -1536,8 +1537,9 @@ public:
{
testcase("canApplyToBrokerCover: amendment disabled");
Env const envOff{*this, testableAmendments() - fixCleanup3_2_0};
auto sle = std::make_shared<SLE>(ltLOAN_BROKER, uint256{1u});
sle->at(sfCoverAvailable) = Number{10};
auto broker = std::make_shared<SLE>(Keylet{ltLOAN_BROKER, uint256{1u}});
broker->at(sfCoverAvailable) = Number{10};
LoanBrokerEntry<ReadView> sle{broker, *envOff.current()};
BEAST_EXPECT(
canApplyToBrokerCover(
*envOff.current(),