refactor: Use ApplyViewContext everywhere instead of ApplyView+STTx (#7618)

This commit is contained in:
Mayukha Vadari
2026-07-02 13:22:04 -04:00
committed by GitHub
parent 0240203060
commit cecea82835
41 changed files with 244 additions and 235 deletions

View File

@@ -11,6 +11,7 @@
#include <xrpl/protocol/MPTIssue.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/STVector256.h>
#include <cstdint>
@@ -411,6 +412,12 @@ public:
emptyDirDelete(Keylet const& directory);
};
struct ApplyViewContext
{
ApplyView& view;
STTx const& tx;
};
namespace directory {
/** Helper functions for managing low-level directory operations.
These are not part of the ApplyView interface.

View File

@@ -210,8 +210,7 @@ canWithdraw(ReadView const& view, STTx const& tx);
[[nodiscard]] TER
doWithdraw(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
AccountID const& senderAcct,
AccountID const& dstAcct,
AccountID const& sourceAcct,

View File

@@ -9,7 +9,6 @@
#include <xrpl/protocol/Rate.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/XRPAmount.h>
@@ -99,8 +98,7 @@ accountReserve(ReadView const& view, AccountID const& id, beast::Journal j, Adju
*/
[[nodiscard]] TER
checkInsufficientReserve(
ApplyView const& view,
STTx const& tx,
ApplyViewContext ctx,
SLE::const_ref accSle,
STAmount const& accBalance,
SLE::const_ref sponsorSle,

View File

@@ -20,7 +20,6 @@
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/UintTypes.h>
@@ -29,8 +28,7 @@ namespace xrpl {
template <ValidIssueType T>
TER
escrowUnlockApplyHelper(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
Rate lockedRate,
SLE::ref sleDest,
STAmount const& xrpBalance,
@@ -44,8 +42,7 @@ escrowUnlockApplyHelper(
template <>
inline TER
escrowUnlockApplyHelper<Issue>(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
Rate lockedRate,
SLE::ref sleDest,
STAmount const& xrpBalance,
@@ -68,15 +65,15 @@ escrowUnlockApplyHelper<Issue>(
if (receiverIssuer)
return tesSUCCESS;
if (!view.exists(trustLineKey) && createAsset)
if (!ctx.view.exists(trustLineKey) && createAsset)
{
// Can the account cover the trust line's reserve?
auto const sponsorSle = getTxReserveSponsor(view, tx);
auto const sponsorSle = getTxReserveSponsor(ctx);
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
if (auto const ret = checkInsufficientReserve(
view, tx, sleDest, xrpBalance, *sponsorSle, {.ownerCountDelta = 1}, journal);
ctx, sleDest, xrpBalance, *sponsorSle, {.ownerCountDelta = 1}, journal);
!isTesSuccess(ret))
{
JLOG(journal.trace()) << "Trust line does not exist. "
@@ -90,7 +87,7 @@ escrowUnlockApplyHelper<Issue>(
initialBalance.get<Issue>().account = noAccount();
if (TER const ter = trustCreate(
view, // payment sandbox
ctx.view, // payment sandbox
recvLow, // is dest low?
issuer, // source
receiver, // destination
@@ -111,13 +108,13 @@ escrowUnlockApplyHelper<Issue>(
return ter; // LCOV_EXCL_LINE
}
view.update(sleDest);
ctx.view.update(sleDest);
}
if (!view.exists(trustLineKey) && !receiverIssuer)
if (!ctx.view.exists(trustLineKey) && !receiverIssuer)
return tecNO_LINE;
auto const xferRate = transferRate(view, amount);
auto const xferRate = transferRate(ctx.view, amount);
// update if issuer rate is less than locked rate
if (xferRate < lockedRate)
lockedRate = xferRate;
@@ -145,7 +142,7 @@ escrowUnlockApplyHelper<Issue>(
// of the funds
if (!createAsset)
{
auto const sleRippleState = view.peek(trustLineKey);
auto const sleRippleState = ctx.view.peek(trustLineKey);
if (!sleRippleState)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -171,7 +168,7 @@ escrowUnlockApplyHelper<Issue>(
// if destination is not the issuer then transfer funds
if (!receiverIssuer)
{
auto const ter = directSendNoFee(view, issuer, receiver, finalAmt, true, journal);
auto const ter = directSendNoFee(ctx.view, issuer, receiver, finalAmt, true, journal);
if (!isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE
}
@@ -181,8 +178,7 @@ escrowUnlockApplyHelper<Issue>(
template <>
inline TER
escrowUnlockApplyHelper<MPTIssue>(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
Rate lockedRate,
SLE::ref sleDest,
STAmount const& xrpBalance,
@@ -199,33 +195,33 @@ escrowUnlockApplyHelper<MPTIssue>(
auto const mptID = amount.get<MPTIssue>().getMptID();
auto const issuanceKey = keylet::mptokenIssuance(mptID);
auto const mptKeylet = keylet::mptoken(issuanceKey.key, receiver);
if (!view.exists(mptKeylet) && createAsset && !receiverIssuer)
if (!ctx.view.exists(mptKeylet) && createAsset && !receiverIssuer)
{
auto const sponsorSle = getTxReserveSponsor(view, tx);
auto const sponsorSle = getTxReserveSponsor(ctx);
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
if (auto const ret = checkInsufficientReserve(
view, tx, sleDest, xrpBalance, *sponsorSle, {.ownerCountDelta = 1}, journal);
ctx, sleDest, xrpBalance, *sponsorSle, {.ownerCountDelta = 1}, journal);
!isTesSuccess(ret))
return ret;
if (auto const ter = createMPToken(view, mptID, receiver, *sponsorSle, 0);
if (auto const ter = createMPToken(ctx.view, mptID, receiver, *sponsorSle, 0);
!isTesSuccess(ter))
{
return ter; // LCOV_EXCL_LINE
}
// update owner count.
increaseOwnerCount(view, sleDest, *sponsorSle, 1, journal);
auto mptSle = view.peek(mptKeylet);
increaseOwnerCount(ctx.view, sleDest, *sponsorSle, 1, journal);
auto mptSle = ctx.view.peek(mptKeylet);
addSponsorToLedgerEntry(mptSle, *sponsorSle);
}
if (!view.exists(mptKeylet) && !receiverIssuer)
if (!ctx.view.exists(mptKeylet) && !receiverIssuer)
return tecNO_PERMISSION;
auto const xferRate = transferRate(view, amount);
auto const xferRate = transferRate(ctx.view, amount);
// update if issuer rate is less than locked rate
if (xferRate < lockedRate)
lockedRate = xferRate;
@@ -248,11 +244,11 @@ escrowUnlockApplyHelper<MPTIssue>(
finalAmt = amount.value() - xferFee;
}
return unlockEscrowMPT(
view,
ctx.view,
sender,
receiver,
finalAmt,
view.rules().enabled(fixTokenEscrowV1) ? amount : finalAmt,
ctx.view.rules().enabled(fixTokenEscrowV1) ? amount : finalAmt,
journal);
}

View File

@@ -10,7 +10,6 @@
#include <xrpl/protocol/Rate.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/UintTypes.h>
#include <xrpl/protocol/XRPAmount.h>
@@ -87,8 +86,7 @@ canAddHolding(ReadView const& view, MPTIssue const& mptIssue);
[[nodiscard]] TER
authorizeMPToken(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
XRPAmount const& priorBalance,
MPTID const& mptIssuanceID,
AccountID const& account,
@@ -119,8 +117,7 @@ requireAuth(
*/
[[nodiscard]] TER
enforceMPTokenAuthorization(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
MPTID const& mptIssuanceID,
AccountID const& account,
XRPAmount const& priorBalance,
@@ -206,8 +203,7 @@ canMPTTradeAndTransfer(
[[nodiscard]] TER
addEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
AccountID const& accountID,
XRPAmount priorBalance,
MPTIssue const& mptIssue,
@@ -215,8 +211,7 @@ addEmptyHolding(
[[nodiscard]] TER
removeEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
AccountID const& accountID,
MPTIssue const& mptIssue,
beast::Journal journal);

View File

@@ -10,7 +10,6 @@
#include <xrpl/protocol/Issue.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/UintTypes.h>
#include <xrpl/protocol/XRPAmount.h>
@@ -237,8 +236,7 @@ canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, Acc
/// canAddHolding() in preflight with the same View and Asset
[[nodiscard]] TER
addEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
AccountID const& accountID,
XRPAmount priorBalance,
Issue const& issue,
@@ -246,7 +244,7 @@ addEmptyHolding(
[[nodiscard]] TER
removeEmptyHolding(
ApplyView& view,
ApplyViewContext ctx,
AccountID const& accountID,
Issue const& issue,
beast::Journal journal);

View File

@@ -42,12 +42,12 @@ getTxReserveSponsorAccountID(STTx const& tx)
}
inline std::expected<SLE::pointer, TER>
getTxReserveSponsor(ApplyView& view, STTx const& tx)
getTxReserveSponsor(ApplyViewContext ctx)
{
auto const sponsorID = getTxReserveSponsorAccountID(tx);
auto const sponsorID = getTxReserveSponsorAccountID(ctx.tx);
if (sponsorID)
{
auto sle = view.peek(keylet::account(*sponsorID));
auto sle = ctx.view.peek(keylet::account(*sponsorID));
// already checked in Transactor::checkSponsor
if (!sle)

View File

@@ -11,7 +11,6 @@
#include <xrpl/protocol/Rate.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/UintTypes.h>
#include <xrpl/protocol/XRPAmount.h>
@@ -304,8 +303,7 @@ canAddHolding(ReadView const& view, Asset const& asset);
[[nodiscard]] TER
addEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
AccountID const& accountID,
XRPAmount priorBalance,
Asset const& asset,
@@ -313,8 +311,7 @@ addEmptyHolding(
[[nodiscard]] TER
removeEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
AccountID const& accountID,
Asset const& asset,
beast::Journal journal);

View File

@@ -127,6 +127,15 @@ public:
TER
checkInvariants(TER const result, XRPAmount const fee);
ApplyViewContext
getApplyViewContext()
{
XRPL_ASSERT(
view_.has_value(),
"xrpl::ApplyContext::getApplyViewContext : view_ emplaced in constructor");
return {.view = *view_, .tx = tx};
}
private:
static TER
failInvariantCheck(TER const result);

View File

@@ -76,7 +76,7 @@ public:
beast::Journal const& j) override;
static std::expected<MPTID, TER>
create(ApplyView& view, STTx const& tx, beast::Journal journal, MPTCreateArgs const& args);
create(ApplyViewContext ctx, beast::Journal journal, MPTCreateArgs const& args);
};
} // namespace xrpl

View File

@@ -432,8 +432,7 @@ canWithdraw(ReadView const& view, STTx const& tx)
TER
doWithdraw(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
AccountID const& senderAcct,
AccountID const& dstAcct,
AccountID const& sourceAcct,
@@ -444,20 +443,20 @@ doWithdraw(
// Create trust line or MPToken for the receiving account
if (dstAcct == senderAcct)
{
if (auto const ter = addEmptyHolding(view, tx, senderAcct, priorBalance, amount.asset(), j);
if (auto const ter = addEmptyHolding(ctx, senderAcct, priorBalance, amount.asset(), j);
!isTesSuccess(ter) && ter != tecDUPLICATE)
return ter;
}
else
{
auto dstSle = view.read(keylet::account(dstAcct));
if (auto err = verifyDepositPreauth(tx, view, senderAcct, dstAcct, dstSle, j))
auto dstSle = ctx.view.read(keylet::account(dstAcct));
if (auto err = verifyDepositPreauth(ctx.tx, ctx.view, senderAcct, dstAcct, dstSle, j))
return err;
}
// Sanity check
if (accountHolds(
view,
ctx.view,
sourceAcct,
amount.asset(),
FreezeHandling::IgnoreFreeze,
@@ -470,13 +469,14 @@ doWithdraw(
// LCOV_EXCL_STOP
}
auto const sponsorSle = getTxReserveSponsor(view, tx);
auto const sponsorSle = getTxReserveSponsor(ctx);
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
// Move the funds directly from the broker's pseudo-account to the
// dstAcct
return accountSend(view, sourceAcct, dstAcct, amount, j, *sponsorSle, WaiveTransferFee::Yes);
return accountSend(
ctx.view, sourceAcct, dstAcct, amount, j, *sponsorSle, WaiveTransferFee::Yes);
}
TER

View File

@@ -330,8 +330,7 @@ accountReserve(ReadView const& view, SLE::const_ref sle, beast::Journal j, Adjus
TER
checkInsufficientReserve(
ApplyView const& view,
STTx const& tx,
ApplyViewContext ctx,
SLE::const_ref accSle,
STAmount const& accBalance,
SLE::const_ref sponsorSle,
@@ -340,14 +339,14 @@ checkInsufficientReserve(
{
if (sponsorSle)
{
auto const sle = view.read(
auto const sle = ctx.view.read(
keylet::sponsorship(
sponsorSle->getAccountID(sfAccount), accSle->getAccountID(sfAccount)));
// A reserve-sponsored tx must carry a sponsor signature
// (cosigning path) and/or have a pre-existing sponsorship SLE
// (prefunded path). Absence of both is an internal invariant break.
if (isReserveSponsored(tx) && !sle && !tx.isFieldPresent(sfSponsorSignature))
if (isReserveSponsored(ctx.tx) && !sle && !ctx.tx.isFieldPresent(sfSponsorSignature))
return tecINTERNAL; // LCOV_EXCL_LINE
if (sle)
@@ -359,14 +358,14 @@ checkInsufficientReserve(
}
auto const sponsorBalance = sponsorSle->getFieldAmount(sfBalance);
STAmount const sponsorReserve = accountReserve(view, sponsorSle, j, adj);
STAmount const sponsorReserve = accountReserve(ctx.view, sponsorSle, j, adj);
if (sponsorBalance < sponsorReserve)
return tecINSUFFICIENT_RESERVE;
}
else
{
STAmount const reserve = accountReserve(view, accSle, j, adj);
STAmount const reserve = accountReserve(ctx.view, accSle, j, adj);
if (accBalance < reserve)
return tecINSUFFICIENT_RESERVE;
}

View File

@@ -23,7 +23,6 @@
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/UintTypes.h>
@@ -127,31 +126,29 @@ canAddHolding(ReadView const& view, MPTIssue const& mptIssue)
[[nodiscard]] TER
addEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
AccountID const& accountID,
XRPAmount priorBalance,
MPTIssue const& mptIssue,
beast::Journal journal)
{
auto const& mptID = mptIssue.getMptID();
auto const mpt = view.peek(keylet::mptokenIssuance(mptID));
auto const mpt = ctx.view.peek(keylet::mptokenIssuance(mptID));
if (!mpt)
return tefINTERNAL; // LCOV_EXCL_LINE
if (mpt->isFlag(lsfMPTLocked))
return tefINTERNAL; // LCOV_EXCL_LINE
if (view.peek(keylet::mptoken(mptID, accountID)))
if (ctx.view.peek(keylet::mptoken(mptID, accountID)))
return tecDUPLICATE;
if (accountID == mptIssue.getIssuer())
return tesSUCCESS;
return authorizeMPToken(view, tx, priorBalance, mptID, accountID, journal, 0, std::nullopt);
return authorizeMPToken(ctx, priorBalance, mptID, accountID, journal, 0, std::nullopt);
}
[[nodiscard]] TER
authorizeMPToken(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
XRPAmount const& priorBalance,
MPTID const& mptIssuanceID,
AccountID const& account,
@@ -159,7 +156,7 @@ authorizeMPToken(
std::uint32_t flags,
std::optional<AccountID> holderID)
{
auto const sleAcct = view.peek(keylet::account(account));
auto const sleAcct = ctx.view.peek(keylet::account(account));
if (!sleAcct)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -174,19 +171,19 @@ authorizeMPToken(
if ((flags & tfMPTUnauthorize) != 0u)
{
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
auto const sleMpt = view.peek(mptokenKey);
auto const sleMpt = ctx.view.peek(mptokenKey);
if (!sleMpt || (*sleMpt)[sfMPTAmount] != 0 ||
(view.rules().enabled(fixCleanup3_1_3) &&
(ctx.view.rules().enabled(fixCleanup3_1_3) &&
(*sleMpt)[~sfLockedAmount].valueOr(0) != 0))
return tecINTERNAL; // LCOV_EXCL_LINE
if (!view.dirRemove(
if (!ctx.view.dirRemove(
keylet::ownerDir(account), (*sleMpt)[sfOwnerNode], sleMpt->key(), false))
return tecINTERNAL; // LCOV_EXCL_LINE
decreaseOwnerCountForObject(view, sleAcct, sleMpt, 1, journal);
decreaseOwnerCountForObject(ctx.view, sleAcct, sleMpt, 1, journal);
view.erase(sleMpt);
ctx.view.erase(sleMpt);
return tesSUCCESS;
}
@@ -195,9 +192,9 @@ authorizeMPToken(
// - create the MPToken object for the holder
SLE::pointer sponsorSle;
if (account == tx[sfAccount])
if (account == ctx.tx[sfAccount])
{
auto sle = getTxReserveSponsor(view, tx);
auto sle = getTxReserveSponsor(ctx);
if (!sle)
return sle.error(); // LCOV_EXCL_LINE
sponsorSle = std::move(*sle);
@@ -214,40 +211,40 @@ authorizeMPToken(
if (sponsorSle || ownerCount(sleAcct, journal) >= 2)
{
if (auto const ret = checkInsufficientReserve(
view, tx, sleAcct, priorBalance, sponsorSle, {.ownerCountDelta = 1}, journal);
ctx, sleAcct, priorBalance, sponsorSle, {.ownerCountDelta = 1}, journal);
!isTesSuccess(ret))
return ret;
}
// Defensive check before we attempt to create MPToken for the issuer
auto const mpt = view.read(keylet::mptokenIssuance(mptIssuanceID));
auto const mpt = ctx.view.read(keylet::mptokenIssuance(mptIssuanceID));
if (!mpt || mpt->getAccountID(sfIssuer) == account)
{
// LCOV_EXCL_START
UNREACHABLE("xrpl::authorizeMPToken : invalid issuance or issuers token");
if (view.rules().enabled(featureLendingProtocol))
if (ctx.view.rules().enabled(featureLendingProtocol))
return tecINTERNAL;
// LCOV_EXCL_STOP
}
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
auto mptoken = std::make_shared<SLE>(mptokenKey);
if (auto ter = dirLink(view, account, mptoken))
if (auto ter = dirLink(ctx.view, account, mptoken))
return ter; // LCOV_EXCL_LINE
(*mptoken)[sfAccount] = account;
(*mptoken)[sfMPTokenIssuanceID] = mptIssuanceID;
(*mptoken)[sfFlags] = 0;
view.insert(mptoken);
ctx.view.insert(mptoken);
// Update owner count.
increaseOwnerCount(view, sleAcct, sponsorSle, 1, journal);
increaseOwnerCount(ctx.view, sleAcct, sponsorSle, 1, journal);
addSponsorToLedgerEntry(mptoken, sponsorSle);
return tesSUCCESS;
}
auto const sleMptIssuance = view.read(keylet::mptokenIssuance(mptIssuanceID));
auto const sleMptIssuance = ctx.view.read(keylet::mptokenIssuance(mptIssuanceID));
if (!sleMptIssuance)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -257,7 +254,7 @@ authorizeMPToken(
if (account != (*sleMptIssuance)[sfIssuer])
return tecINTERNAL; // LCOV_EXCL_LINE
auto const sleMpt = view.peek(keylet::mptoken(mptIssuanceID, *holderID));
auto const sleMpt = ctx.view.peek(keylet::mptoken(mptIssuanceID, *holderID));
if (!sleMpt)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -280,14 +277,13 @@ authorizeMPToken(
if (flagsIn != flagsOut)
sleMpt->setFieldU32(sfFlags, flagsOut);
view.update(sleMpt);
ctx.view.update(sleMpt);
return tesSUCCESS;
}
[[nodiscard]] TER
removeEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
AccountID const& accountID,
MPTIssue const& mptIssue,
beast::Journal journal)
@@ -297,7 +293,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));
auto const mptoken = ctx.view.peek(keylet::mptoken(mptID, accountID));
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
@@ -305,7 +301,7 @@ removeEmptyHolding(
// accounting out of balance, so fail. Since this should be impossible
// anyway, I'm not going to put any effort into it.
if (mptoken->at(sfMPTAmount) != 0 ||
(view.rules().enabled(fixCleanup3_1_3) && (*mptoken)[~sfLockedAmount].valueOr(0) != 0))
(ctx.view.rules().enabled(fixCleanup3_1_3) && (*mptoken)[~sfLockedAmount].valueOr(0) != 0))
return tecHAS_OBLIGATIONS;
// Don't delete if the token still has confidential balances
@@ -318,8 +314,7 @@ removeEmptyHolding(
}
return authorizeMPToken(
view,
tx,
ctx,
{}, // priorBalance
mptID,
accountID,
@@ -438,14 +433,13 @@ requireAuth(
[[nodiscard]] TER
enforceMPTokenAuthorization(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
MPTID const& mptIssuanceID,
AccountID const& account,
XRPAmount const& priorBalance, // for MPToken authorization
beast::Journal j)
{
auto const sleIssuance = view.read(keylet::mptokenIssuance(mptIssuanceID));
auto const sleIssuance = ctx.view.read(keylet::mptokenIssuance(mptIssuanceID));
if (!sleIssuance)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -457,7 +451,7 @@ enforceMPTokenAuthorization(
return tefINTERNAL; // LCOV_EXCL_LINE
auto const keylet = keylet::mptoken(mptIssuanceID, account);
auto const sleToken = view.read(keylet); // NOTE: might be null
auto const sleToken = ctx.view.read(keylet); // NOTE: might be null
auto const maybeDomainID = sleIssuance->at(~sfDomainID);
bool expired = false;
bool const authorizedByDomain = [&]() -> bool {
@@ -465,7 +459,7 @@ enforceMPTokenAuthorization(
if (!maybeDomainID.has_value())
return false; // LCOV_EXCL_LINE
auto const ter = verifyValidDomain(view, account, *maybeDomainID, j);
auto const ter = verifyValidDomain(ctx.view, account, *maybeDomainID, j);
if (isTesSuccess(ter))
return true;
if (ter == tecEXPIRED)
@@ -520,8 +514,7 @@ enforceMPTokenAuthorization(
maybeDomainID.has_value() && sleToken == nullptr,
"xrpl::enforceMPTokenAuthorization : new MPToken for domain");
if (auto const err = authorizeMPToken(
view,
tx,
ctx,
priorBalance, // priorBalance
mptIssuanceID, // mptIssuanceID
account, // account

View File

@@ -22,7 +22,6 @@
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/UintTypes.h>
#include <xrpl/protocol/XRPAmount.h>
@@ -634,8 +633,7 @@ canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, Acc
TER
addEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
AccountID const& accountID,
XRPAmount priorBalance,
Issue const& issue,
@@ -647,29 +645,29 @@ addEmptyHolding(
auto const& issuerId = issue.getIssuer();
auto const& currency = issue.currency;
if (isGlobalFrozen(view, issuerId))
if (isGlobalFrozen(ctx.view, issuerId))
return tecFROZEN; // LCOV_EXCL_LINE
auto const& srcId = issuerId;
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));
auto const sleSrc = ctx.view.peek(keylet::account(srcId));
auto const sleDst = ctx.view.peek(keylet::account(dstId));
if (!sleDst || !sleSrc)
return tefINTERNAL; // LCOV_EXCL_LINE
if (!sleSrc->isFlag(lsfDefaultRipple))
return tecINTERNAL; // LCOV_EXCL_LINE
// If the line already exists, don't create it again.
if (view.read(index))
if (ctx.view.read(index))
return tecDUPLICATE;
SLE::pointer sponsorSle;
// A reserve sponsor only covers tx.Account's own objects.
if (!isPseudoAccount(sleDst) && accountID == tx[sfAccount])
if (!isPseudoAccount(sleDst) && accountID == ctx.tx[sfAccount])
{
auto sle = getTxReserveSponsor(view, tx);
auto sle = getTxReserveSponsor(ctx);
if (!sle)
return sle.error(); // LCOV_EXCL_LINE
sponsorSle = std::move(*sle);
@@ -677,12 +675,12 @@ addEmptyHolding(
// Can the account cover the trust line reserve ?
if (auto const ret = checkInsufficientReserve(
view, tx, sleDst, priorBalance, sponsorSle, {.ownerCountDelta = 1}, journal);
ctx, sleDst, priorBalance, sponsorSle, {.ownerCountDelta = 1}, journal);
!isTesSuccess(ret))
return tecNO_LINE_INSUF_RESERVE;
return trustCreate(
view,
ctx.view,
high,
srcId,
dstId,
@@ -702,14 +700,14 @@ addEmptyHolding(
TER
removeEmptyHolding(
ApplyView& view,
ApplyViewContext ctx,
AccountID const& accountID,
Issue const& issue,
beast::Journal journal)
{
if (issue.native())
{
auto const sle = view.read(keylet::account(accountID));
auto const sle = ctx.view.read(keylet::account(accountID));
if (!sle)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -724,7 +722,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));
auto const line = ctx.view.peek(keylet::trustLine(accountID, issue));
if (!line)
return accountIsIssuer ? (TER)tesSUCCESS : (TER)tecOBJECT_NOT_FOUND;
if (!accountIsIssuer && line->at(sfBalance)->iou() != beast::kZero)
@@ -734,13 +732,13 @@ removeEmptyHolding(
if (line->isFlag(lsfLowReserve))
{
// Clear reserve for low account.
auto sleLowAccount = view.peek(keylet::account(line->at(sfLowLimit)->getIssuer()));
auto sleLowAccount = ctx.view.peek(keylet::account(line->at(sfLowLimit)->getIssuer()));
if (!sleLowAccount)
return tecINTERNAL; // LCOV_EXCL_LINE
auto const currentLowSponsor = getLedgerEntryReserveSponsor(view, line, sfLowSponsor);
auto const currentLowSponsor = getLedgerEntryReserveSponsor(ctx.view, line, sfLowSponsor);
decreaseOwnerCount(view, sleLowAccount, currentLowSponsor, 1, journal);
decreaseOwnerCount(ctx.view, sleLowAccount, currentLowSponsor, 1, journal);
// It's not really necessary to clear the reserve flag, since the line
// is about to be deleted, but this will make the metadata reflect an
// accurate state at the time of deletion.
@@ -751,13 +749,13 @@ removeEmptyHolding(
if (line->isFlag(lsfHighReserve))
{
// Clear reserve for high account.
auto sleHighAccount = view.peek(keylet::account(line->at(sfHighLimit)->getIssuer()));
auto sleHighAccount = ctx.view.peek(keylet::account(line->at(sfHighLimit)->getIssuer()));
if (!sleHighAccount)
return tecINTERNAL; // LCOV_EXCL_LINE
auto const currentHighSponsor = getLedgerEntryReserveSponsor(view, line, sfHighSponsor);
auto const currentHighSponsor = getLedgerEntryReserveSponsor(ctx.view, line, sfHighSponsor);
decreaseOwnerCount(view, sleHighAccount, currentHighSponsor, 1, journal);
decreaseOwnerCount(ctx.view, sleHighAccount, currentHighSponsor, 1, journal);
// It's not really necessary to clear the reserve flag, since the line
// is about to be deleted, but this will make the metadata reflect an
// accurate state at the time of deletion.
@@ -766,7 +764,11 @@ removeEmptyHolding(
}
return trustDelete(
view, line, line->at(sfLowLimit)->getIssuer(), line->at(sfHighLimit)->getIssuer(), journal);
ctx.view,
line,
line->at(sfLowLimit)->getIssuer(),
line->at(sfHighLimit)->getIssuer(),
journal);
}
TER

View File

@@ -24,7 +24,6 @@
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/UintTypes.h>
#include <xrpl/protocol/XRPAmount.h>
@@ -573,8 +572,7 @@ canAddHolding(ReadView const& view, Asset const& asset)
TER
addEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
AccountID const& accountID,
XRPAmount priorBalance,
Asset const& asset,
@@ -582,29 +580,21 @@ addEmptyHolding(
{
return std::visit(
[&]<ValidIssueType TIss>(TIss const& issue) -> TER {
return addEmptyHolding(view, tx, accountID, priorBalance, issue, journal);
return addEmptyHolding(ctx, accountID, priorBalance, issue, journal);
},
asset.value());
}
TER
removeEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
AccountID const& accountID,
Asset const& asset,
beast::Journal journal)
{
return std::visit(
[&]<ValidIssueType TIss>(TIss const& issue) -> TER {
if constexpr (std::is_same_v<TIss, Issue>)
{
return removeEmptyHolding(view, accountID, issue, journal);
}
else
{
return removeEmptyHolding(view, tx, accountID, issue, journal);
}
return removeEmptyHolding(ctx, accountID, issue, journal);
},
asset.value());
}

View File

@@ -207,7 +207,7 @@ SponsorshipSet::doApply()
bool const hasPositiveFeeAmount = feeAmount.has_value() && *feeAmount > beast::kZero;
auto reserveSponsorAccSle = getTxReserveSponsor(view(), ctx_.tx);
auto reserveSponsorAccSle = getTxReserveSponsor(ctx_.getApplyViewContext());
if (!reserveSponsorAccSle)
return reserveSponsorAccSle.error(); // LCOV_EXCL_LINE
@@ -226,8 +226,7 @@ SponsorshipSet::doApply()
sponsorBalanceAfterFee -= *feeAmount;
if (auto const ret = checkInsufficientReserve(
ctx_.view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sponsorAccSle,
sponsorBalanceAfterFee.xrp(),
*reserveSponsorAccSle,
@@ -294,8 +293,7 @@ SponsorshipSet::doApply()
sponsorBalanceAfterFee -= feeAmountDelta;
if (auto const ret = checkInsufficientReserve(
ctx_.view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sponsorAccSle,
sponsorBalanceAfterFee.xrp(),
*reserveSponsorAccSle,

View File

@@ -322,8 +322,7 @@ SponsorshipTransfer::doApply()
// check new sponsor have sufficient balance
// NOLINTNEXTLINE(readability-suspicious-call-argument)
if (auto const ter = checkInsufficientReserve(
ctx_.view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sponseeSle,
sponseeSle->getFieldAmount(sfBalance),
newSponsorSle,
@@ -376,8 +375,7 @@ SponsorshipTransfer::doApply()
// check new sponsor have sufficient balance
// NOLINTNEXTLINE(readability-suspicious-call-argument)
if (auto const ter = checkInsufficientReserve(
ctx_.view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sponseeSle,
sponseeSle->getFieldAmount(sfBalance),
newSponsorSle,
@@ -425,8 +423,7 @@ SponsorshipTransfer::doApply()
// The owner takes the reserve burden back when the object is
// no longer sponsored.
if (auto const ter = checkInsufficientReserve(
ctx_.view(),
ctx_.tx,
ctx_.getApplyViewContext(),
ownerSle,
balanceBeforeFee(ownerSle),
SLE::pointer(),
@@ -466,8 +463,7 @@ SponsorshipTransfer::doApply()
return tefINTERNAL; // LCOV_EXCL_LINE
if (auto const ter = checkInsufficientReserve(
ctx_.view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sponseeSle,
sponseeSle->getFieldAmount(sfBalance),
newSponsorSle,
@@ -495,8 +491,7 @@ SponsorshipTransfer::doApply()
return tefINTERNAL; // LCOV_EXCL_LINE
if (auto const ter = checkInsufficientReserve(
ctx_.view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sponseeSle,
sponseeSle->getFieldAmount(sfBalance),
newSponsorSle,
@@ -532,8 +527,7 @@ SponsorshipTransfer::doApply()
// The sponsee must be able to hold its own account reserve after
// the sponsorship is removed.
if (auto const ter = checkInsufficientReserve(
ctx_.view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sponseeSle,
balanceBeforeFee(sponseeSle),
SLE::pointer(),

View File

@@ -319,12 +319,11 @@ SignerListSet::replaceSignerList()
// We check the reserve against the starting balance because we want to
// allow dipping into the reserve to pay fees. This behavior is consistent
// with TicketCreate.
auto const sponsorSle = getTxReserveSponsor(view(), ctx_.tx);
auto const sponsorSle = getTxReserveSponsor(ctx_.getApplyViewContext());
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
if (auto const ret = checkInsufficientReserve(
ctx_.view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sle,
preFeeBalance_,
*sponsorSle,

View File

@@ -3,6 +3,7 @@
#include <xrpl/basics/Log.h>
#include <xrpl/basics/scope.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
@@ -388,7 +389,8 @@ CheckCash::doApply()
STAmount const flowDeliver{
optDeliverMin ? maxDeliverMin() : ctx_.tx.getFieldAmount(sfAmount)};
auto const sponsorSle = getTxReserveSponsor(psb, ctx_.tx);
auto applyViewContext = ApplyViewContext({.view = psb, .tx = ctx_.tx});
auto const sponsorSle = getTxReserveSponsor(applyViewContext);
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
@@ -399,8 +401,7 @@ CheckCash::doApply()
// Can the account cover the trust line's or MPT reserve?
if (auto const ret = checkInsufficientReserve(
psb,
ctx_.tx,
applyViewContext,
sleDst,
preFeeBalance_,
*sponsorSle,

View File

@@ -195,12 +195,11 @@ CheckCreate::doApply()
// A check counts against the reserve of the issuing account, but we
// check the starting balance because we want to allow dipping into the
// reserve to pay fees.
auto const sponsorSle = getTxReserveSponsor(view(), ctx_.tx);
auto const sponsorSle = getTxReserveSponsor(ctx_.getApplyViewContext());
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
if (auto const ret = checkInsufficientReserve(
view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sle,
preFeeBalance_,
*sponsorSle,

View File

@@ -99,12 +99,11 @@ DelegateSet::doApply()
if (permissions.empty())
return tecINTERNAL; // LCOV_EXCL_LINE
auto const sponsorSle = getTxReserveSponsor(view(), ctx_.tx);
auto const sponsorSle = getTxReserveSponsor(ctx_.getApplyViewContext());
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
if (auto const ret = checkInsufficientReserve(
view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sleOwner,
preFeeBalance_,
*sponsorSle,

View File

@@ -181,8 +181,7 @@ EscrowCancel::doApply()
if (auto const ret = std::visit(
[&]<typename T>(T const&) {
return escrowUnlockApplyHelper<T>(
ctx_.view(),
ctx_.tx,
ctx_.getApplyViewContext(),
kParityRate,
ctx_.view().rules().enabled(fixCleanup3_2_0) ? sle : slep,
preFeeBalance_,

View File

@@ -437,7 +437,7 @@ EscrowCreate::doApply()
STAmount const amount{ctx_.tx[sfAmount]};
auto const balance = sle->getFieldAmount(sfBalance).xrp();
auto const sponsorSle = getTxReserveSponsor(view(), ctx_.tx);
auto const sponsorSle = getTxReserveSponsor(ctx_.getApplyViewContext());
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
// First check: whoever is on the hook for the new owner increment
@@ -446,7 +446,7 @@ EscrowCreate::doApply()
// unsponsored this hits the source branch and validates the
// source's pre-lock balance against base + (currentOC+1)*increment.
if (auto const ret = checkInsufficientReserve(
ctx_.view(), ctx_.tx, sle, balance, *sponsorSle, {.ownerCountDelta = 1}, j_);
ctx_.getApplyViewContext(), sle, balance, *sponsorSle, {.ownerCountDelta = 1}, j_);
!isTesSuccess(ret))
return ret;
@@ -463,8 +463,7 @@ EscrowCreate::doApply()
// - unsponsored: adj=1 — source owes base + the new increment.
std::int32_t const ownerCountAdj = *sponsorSle ? 0 : 1;
if (auto const ret = checkInsufficientReserve(
ctx_.view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sle,
balance - STAmount(amount).xrp(),
{},

View File

@@ -365,8 +365,7 @@ EscrowFinish::doApply()
if (auto const ret = std::visit(
[&]<typename T>(T const&) {
return escrowUnlockApplyHelper<T>(
ctx_.view(),
ctx_.tx,
ctx_.getApplyViewContext(),
lockedRate,
sled,
preFeeBalance_,

View File

@@ -211,7 +211,14 @@ LoanBrokerCoverWithdraw::doApply()
associateAsset(*broker, vaultAsset);
return doWithdraw(view(), tx, accountID_, dstAcct, brokerPseudoID, preFeeBalance_, amount, j_);
return doWithdraw(
ctx_.getApplyViewContext(),
accountID_,
dstAcct,
brokerPseudoID,
preFeeBalance_,
amount,
j_);
}
void

View File

@@ -159,7 +159,7 @@ LoanBrokerDelete::doApply()
return ter;
}
if (auto ter = removeEmptyHolding(view(), tx, brokerPseudoID, vaultAsset, j_))
if (auto ter = removeEmptyHolding(ctx_.getApplyViewContext(), brokerPseudoID, vaultAsset, j_))
return ter;
auto brokerPseudoSLE = view().peek(keylet::account(brokerPseudoID));

View File

@@ -248,8 +248,8 @@ LoanBrokerSet::doApply()
auto& pseudo = *maybePseudo;
auto pseudoId = pseudo->at(sfAccount);
if (auto ter =
addEmptyHolding(view, tx, pseudoId, preFeeBalance_, sleVault->at(sfAsset), j_))
if (auto ter = addEmptyHolding(
ctx_.getApplyViewContext(), pseudoId, preFeeBalance_, sleVault->at(sfAsset), j_))
return ter;
// Initialize data fields:

View File

@@ -625,7 +625,11 @@ LoanPay::doApply()
{
// The broker may have deleted their holding. Recreate it if needed
if (auto const ter = addEmptyHolding(
view, tx, brokerPayee, brokerPayeeSle->at(sfBalance).value().xrp(), asset, j_);
ctx_.getApplyViewContext(),
brokerPayee,
brokerPayeeSle->at(sfBalance).value().xrp(),
asset,
j_);
ter && ter != tecDUPLICATE)
{
// ignore tecDUPLICATE. That means the holding already exists,

View File

@@ -538,8 +538,9 @@ LoanSet::doApply()
borrower == accountID_ || borrower == counterparty,
"xrpl::LoanSet::doApply",
"borrower signed transaction");
auto applyViewContext = ctx_.getApplyViewContext();
if (auto const ter = addEmptyHolding(
view, tx, borrower, borrowerSle->at(sfBalance).value().xrp(), vaultAsset, j_);
applyViewContext, borrower, borrowerSle->at(sfBalance).value().xrp(), vaultAsset, j_);
ter && ter != tecDUPLICATE)
{
// ignore tecDUPLICATE. That means the holding already exists, and
@@ -562,7 +563,11 @@ LoanSet::doApply()
"broker owner signed transaction");
if (auto const ter = addEmptyHolding(
view, tx, brokerOwner, brokerOwnerSle->at(sfBalance).value().xrp(), vaultAsset, j_);
applyViewContext,
brokerOwner,
brokerOwnerSle->at(sfBalance).value().xrp(),
vaultAsset,
j_);
ter && ter != tecDUPLICATE)
{
// ignore tecDUPLICATE. That means the holding already exists,

View File

@@ -152,6 +152,7 @@ DepositPreauth::preclaim(PreclaimContext const& ctx)
TER
DepositPreauth::doApply()
{
auto applyViewContext = ctx_.getApplyViewContext();
if (ctx_.tx.isFieldPresent(sfAuthorize))
{
auto const sleOwner = view().peek(keylet::account(accountID_));
@@ -161,11 +162,16 @@ DepositPreauth::doApply()
// A preauth counts against the reserve of the issuing account, but we
// check the starting balance because we want to allow dipping into the
// reserve to pay fees.
auto const sponsorSle = getTxReserveSponsor(view(), ctx_.tx);
auto const sponsorSle = getTxReserveSponsor(applyViewContext);
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
if (auto const ret = checkInsufficientReserve(
view(), ctx_.tx, sleOwner, preFeeBalance_, *sponsorSle, {.ownerCountDelta = 1}, j_);
applyViewContext,
sleOwner,
preFeeBalance_,
*sponsorSle,
{.ownerCountDelta = 1},
j_);
!isTesSuccess(ret))
return ret;
@@ -209,11 +215,16 @@ DepositPreauth::doApply()
// A preauth counts against the reserve of the issuing account, but we
// check the starting balance because we want to allow dipping into the
// reserve to pay fees.
auto const sponsorSle = getTxReserveSponsor(view(), ctx_.tx);
auto const sponsorSle = getTxReserveSponsor(applyViewContext);
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
if (auto const ret = checkInsufficientReserve(
view(), ctx_.tx, sleOwner, preFeeBalance_, *sponsorSle, {.ownerCountDelta = 1}, j_);
applyViewContext,
sleOwner,
preFeeBalance_,
*sponsorSle,
{.ownerCountDelta = 1},
j_);
!isTesSuccess(ret))
return ret;

View File

@@ -135,7 +135,7 @@ PaymentChannelCreate::doApply()
return tecEXPIRED;
}
auto const sponsorSle = getTxReserveSponsor(view(), ctx_.tx);
auto const sponsorSle = getTxReserveSponsor(ctx_.getApplyViewContext());
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
@@ -147,7 +147,12 @@ PaymentChannelCreate::doApply()
// unsponsored this hits the source branch and validates the
// source's pre-lock balance against base + (currentOC+1)*increment.
if (auto const ret = checkInsufficientReserve(
ctx_.view(), ctx_.tx, sle, preFeeBalance_, *sponsorSle, {.ownerCountDelta = 1}, j_);
ctx_.getApplyViewContext(),
sle,
preFeeBalance_,
*sponsorSle,
{.ownerCountDelta = 1},
j_);
!isTesSuccess(ret))
return ret;
@@ -161,8 +166,7 @@ PaymentChannelCreate::doApply()
// - unsponsored: adj=1 — source owes base + the new increment.
std::int32_t const ownerCountAdj = *sponsorSle ? 0 : 1;
if (auto const ret = checkInsufficientReserve(
ctx_.view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sle,
preFeeBalance_ - ctx_.tx[sfAmount].xrp(),
{},

View File

@@ -90,16 +90,16 @@ PaymentChannelFund::doApply()
{
// Check reserve and funds availability
auto const balance = (*sle)[sfBalance];
auto const sponsorSle = getTxReserveSponsor(view(), ctx_.tx);
auto const sponsorSle = getTxReserveSponsor(ctx_.getApplyViewContext());
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
if (auto const ret =
checkInsufficientReserve(ctx_.view(), ctx_.tx, sle, balance, *sponsorSle, {}, j_);
if (auto const ret = checkInsufficientReserve(
ctx_.getApplyViewContext(), sle, balance, *sponsorSle, {}, j_);
!isTesSuccess(ret))
return ret;
if (auto const ret = checkInsufficientReserve(
ctx_.view(), ctx_.tx, sle, balance - ctx_.tx[sfAmount], {}, {}, j_);
ctx_.getApplyViewContext(), sle, balance - ctx_.tx[sfAmount], {}, {}, j_);
!isTesSuccess(ret))
return tecUNFUNDED;
}

View File

@@ -164,8 +164,7 @@ MPTokenAuthorize::doApply()
{
auto const& tx = ctx_.tx;
return authorizeMPToken(
ctx_.view(),
tx,
ctx_.getApplyViewContext(),
preFeeBalance_,
tx[sfMPTokenIssuanceID],
accountID_,

View File

@@ -116,19 +116,18 @@ MPTokenIssuanceCreate::preflight(PreflightContext const& ctx)
std::expected<MPTID, TER>
MPTokenIssuanceCreate::create(
ApplyView& view,
STTx const& tx,
ApplyViewContext ctx,
beast::Journal journal,
MPTCreateArgs const& args)
{
auto const acct = view.peek(keylet::account(args.account));
auto const acct = ctx.view.peek(keylet::account(args.account));
if (!acct)
return std::unexpected(tecINTERNAL); // LCOV_EXCL_LINE
SLE::pointer sponsorSle;
if (!isPseudoAccount(acct))
{
auto sle = getTxReserveSponsor(view, tx);
auto sle = getTxReserveSponsor(ctx);
if (!sle)
return std::unexpected(sle.error());
sponsorSle = std::move(*sle);
@@ -137,7 +136,7 @@ MPTokenIssuanceCreate::create(
if (args.priorBalance)
{
if (auto const ret = checkInsufficientReserve(
view, tx, acct, *(args.priorBalance), sponsorSle, {.ownerCountDelta = 1}, journal);
ctx, acct, *(args.priorBalance), sponsorSle, {.ownerCountDelta = 1}, journal);
!isTesSuccess(ret))
return std::unexpected(ret); // tecINSUFFICIENT_RESERVE
}
@@ -147,7 +146,7 @@ MPTokenIssuanceCreate::create(
// create the MPTokenIssuance
{
auto const ownerNode = view.dirInsert(
auto const ownerNode = ctx.view.dirInsert(
keylet::ownerDir(args.account), mptIssuanceKeylet, describeOwnerDir(args.account));
if (!ownerNode)
@@ -185,7 +184,7 @@ MPTokenIssuanceCreate::create(
// populate this after the pseudo-account's MPToken /
// RippleState has been installed. A missing holding here
// would dangle the pointer and is a programmer error.
auto const sleHolding = view.read(keylet::unchecked(*args.referenceHolding));
auto const sleHolding = ctx.view.read(keylet::unchecked(*args.referenceHolding));
if (!sleHolding)
return std::unexpected(tecINTERNAL); // LCOV_EXCL_LINE
auto const type = sleHolding->getType();
@@ -196,11 +195,11 @@ MPTokenIssuanceCreate::create(
addSponsorToLedgerEntry(mptIssuance, sponsorSle);
view.insert(mptIssuance);
ctx.view.insert(mptIssuance);
}
// Update owner count.
increaseOwnerCount(view, acct, sponsorSle, 1, journal);
increaseOwnerCount(ctx.view, acct, sponsorSle, 1, journal);
return mptId;
}
@@ -210,8 +209,7 @@ MPTokenIssuanceCreate::doApply()
{
auto const& tx = ctx_.tx;
auto const result = create(
view(),
tx,
ctx_.getApplyViewContext(),
j_,
{
.priorBalance = preFeeBalance_,

View File

@@ -328,7 +328,7 @@ TrustSet::doApply()
// well. A person with no intention of using the gateway
// could use the extra XRP for their own purposes.
auto const sponsorSle = getTxReserveSponsor(view(), ctx_.tx);
auto const sponsorSle = getTxReserveSponsor(ctx_.getApplyViewContext());
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
@@ -539,8 +539,7 @@ TrustSet::doApply()
// For PreFunded sponsors, we need to check if there are sufficient reserves before
// calling increaseOwnerCount().
if (auto const ret = checkInsufficientReserve(
view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sleLowAccount,
preFeeBalance_,
*sponsorSle,
@@ -574,8 +573,7 @@ TrustSet::doApply()
// For PreFunded sponsors, we need to check if there are sufficient reserves before
// calling increaseOwnerCount().
if (auto const ret = checkInsufficientReserve(
view(),
ctx_.tx,
ctx_.getApplyViewContext(),
sleHighAccount,
preFeeBalance_,
*sponsorSle,
@@ -614,8 +612,8 @@ TrustSet::doApply()
}
// Reserve is not scaled by load.
else if (
auto const ret =
checkInsufficientReserve(view(), ctx_.tx, sle, preFeeBalance_, *sponsorSle, {}, j_);
auto const ret = checkInsufficientReserve(
ctx_.getApplyViewContext(), sle, preFeeBalance_, *sponsorSle, {}, j_);
!freeTrustLine && bReserveIncrease && !isTesSuccess(ret))
{
JLOG(j_.trace()) << "Delay transaction: Insufficent reserve to "
@@ -646,7 +644,12 @@ TrustSet::doApply()
}
else if (
auto const ret = checkInsufficientReserve(
ctx_.view(), ctx_.tx, sle, preFeeBalance_, *sponsorSle, {.ownerCountDelta = 1}, j_);
ctx_.getApplyViewContext(),
sle,
preFeeBalance_,
*sponsorSle,
{.ownerCountDelta = 1},
j_);
!freeTrustLine && !isTesSuccess(ret)) // Reserve is not scaled by load.
{
JLOG(j_.trace()) << "Delay transaction: Line does not exist. "

View File

@@ -399,7 +399,8 @@ VaultClawback::doApply()
// Keep MPToken if holder is the vault owner.
if (holder != vault->at(sfOwner))
{
if (auto const ter = removeEmptyHolding(view(), tx, holder, sharesDestroyed.asset(), j_);
if (auto const ter =
removeEmptyHolding(ctx_.getApplyViewContext(), holder, sharesDestroyed.asset(), j_);
isTesSuccess(ter))
{
JLOG(j_.debug()) //

View File

@@ -146,6 +146,7 @@ VaultCreate::doApply()
// we can consider downgrading them to `tef` or `tem`.
auto const& tx = ctx_.tx;
auto applyViewContext = ctx_.getApplyViewContext();
auto const sequence = tx.getSeqValue();
auto const owner = view().peek(keylet::account(accountID_));
if (owner == nullptr)
@@ -167,7 +168,7 @@ VaultCreate::doApply()
AccountID const pseudoId = pseudo->at(sfAccount);
auto const asset = tx[sfAsset];
if (auto ter = addEmptyHolding(view(), tx, pseudoId, preFeeBalance_, asset, j_);
if (auto ter = addEmptyHolding(applyViewContext, pseudoId, preFeeBalance_, asset, j_);
!isTesSuccess(ter))
return ter;
@@ -197,8 +198,7 @@ VaultCreate::doApply()
: keylet::trustLine(pseudoId, asset.get<Issue>()).key;
}();
auto const maybeShare = MPTokenIssuanceCreate::create(
view(),
tx,
applyViewContext,
j_,
{
.priorBalance = std::nullopt,
@@ -244,8 +244,8 @@ VaultCreate::doApply()
view().insert(vault);
// Explicitly create MPToken for the vault owner
if (auto const err =
authorizeMPToken(view(), tx, preFeeBalance_, mptIssuanceID, accountID_, ctx_.journal);
if (auto const err = authorizeMPToken(
applyViewContext, preFeeBalance_, mptIssuanceID, accountID_, ctx_.journal);
!isTesSuccess(err))
return err;
@@ -253,7 +253,13 @@ VaultCreate::doApply()
if (tx.isFlag(tfVaultPrivate))
{
if (auto const err = authorizeMPToken(
view(), tx, preFeeBalance_, mptIssuanceID, pseudoId, ctx_.journal, {}, accountID_);
applyViewContext,
preFeeBalance_,
mptIssuanceID,
pseudoId,
ctx_.journal,
{},
accountID_);
!isTesSuccess(err))
return err;
}

View File

@@ -96,13 +96,14 @@ TER
VaultDelete::doApply()
{
auto const vault = view().peek(keylet::vault(ctx_.tx[sfVaultID]));
auto applyViewContext = ctx_.getApplyViewContext();
if (!vault)
return tefINTERNAL; // LCOV_EXCL_LINE
// Destroy the asset holding.
auto asset = vault->at(sfAsset);
if (auto ter = removeEmptyHolding(view(), ctx_.tx, vault->at(sfAccount), asset, j_);
if (auto ter = removeEmptyHolding(applyViewContext, vault->at(sfAccount), asset, j_);
!isTesSuccess(ter))
return ter;
@@ -132,7 +133,7 @@ VaultDelete::doApply()
if (auto const mptoken = view().peek(keylet::mptoken(shareMPTID, accountID_)))
{
if (auto const ter =
removeEmptyHolding(view(), ctx_.tx, accountID_, MPTIssue(shareMPTID), j_);
removeEmptyHolding(applyViewContext, accountID_, MPTIssue(shareMPTID), j_);
!isTesSuccess(ter))
{
// LCOV_EXCL_START

View File

@@ -197,6 +197,7 @@ VaultDeposit::doApply()
{
bool const fix320Enabled = view().rules().enabled(fixCleanup3_2_0);
auto const vault = view().peek(keylet::vault(ctx_.tx[sfVaultID]));
auto applyViewContext = ctx_.getApplyViewContext();
if (!vault)
return tefINTERNAL; // LCOV_EXCL_LINE
auto const vaultAsset = vault->at(sfAsset);
@@ -231,7 +232,7 @@ VaultDeposit::doApply()
if (vault->isFlag(lsfVaultPrivate) && accountID_ != vault->at(sfOwner))
{
if (auto const err = enforceMPTokenAuthorization(
ctx_.view(), ctx_.tx, mptIssuanceID, accountID_, preFeeBalance_, j_);
applyViewContext, mptIssuanceID, accountID_, preFeeBalance_, j_);
!isTesSuccess(err))
return err;
}
@@ -241,8 +242,7 @@ VaultDeposit::doApply()
if (!view().exists(keylet::mptoken(mptIssuanceID, accountID_)))
{
if (auto const err = authorizeMPToken(
view(),
ctx_.tx,
applyViewContext,
preFeeBalance_,
mptIssuanceID->value(),
accountID_,
@@ -258,8 +258,7 @@ VaultDeposit::doApply()
XRPL_ASSERT(
accountID_ == vault->at(sfOwner), "xrpl::VaultDeposit::doApply : account is owner");
if (auto const err = authorizeMPToken(
view(),
ctx_.tx,
applyViewContext,
preFeeBalance_, // priorBalance
mptIssuanceID->value(), // mptIssuanceID
sleIssuance->at(sfIssuer), // account

View File

@@ -194,6 +194,7 @@ TER
VaultWithdraw::doApply()
{
auto const vault = view().peek(keylet::vault(ctx_.tx[sfVaultID]));
auto applyViewContext = ctx_.getApplyViewContext();
if (!vault)
return tefINTERNAL; // LCOV_EXCL_LINE
@@ -362,7 +363,7 @@ VaultWithdraw::doApply()
if (accountID_ != vault->at(sfOwner))
{
if (auto const ter =
removeEmptyHolding(view(), ctx_.tx, accountID_, sharesRedeemed.asset(), j_);
removeEmptyHolding(applyViewContext, accountID_, sharesRedeemed.asset(), j_);
isTesSuccess(ter))
{
JLOG(j_.debug()) //
@@ -388,7 +389,7 @@ VaultWithdraw::doApply()
auto const dstAcct = ctx_.tx[~sfDestination].value_or(accountID_);
return doWithdraw(
view(), ctx_.tx, accountID_, dstAcct, vaultAccount, preFeeBalance_, assetsWithdrawn, j_);
applyViewContext, accountID_, dstAcct, vaultAccount, preFeeBalance_, assetsWithdrawn, j_);
}
void

View File

@@ -5930,7 +5930,7 @@ class Vault_test : public beast::unit_test::Suite
auto const dummyTx = *env.jt(noop(holder)).stx;
BEAST_EXPECT(
removeEmptyHolding(sb, dummyTx, holder.id(), MPTIssue(mpt.issuanceID()), j) ==
removeEmptyHolding({sb, dummyTx}, holder.id(), MPTIssue(mpt.issuanceID()), j) ==
tecHAS_OBLIGATIONS);
BEAST_EXPECT(sb.peek(tokenKeylet) != nullptr);
}
@@ -7544,7 +7544,7 @@ class Vault_test : public beast::unit_test::Suite
// Transaction fails if the data field is set, but is empty
{
testcase("VaultDelete memo data featureLendingProtocolV1_1 enabled data empty");
delTx[sfMemoData] = strHex(std::string(0, 'A'));
delTx[sfMemoData] = std::string();
env(delTx, Ter(temMALFORMED));
env.close();
}