Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b6e1b33
PoC: ApplyViewContext
mvadari Jun 24, 2026
20eaf5c
reduce diff
mvadari Jun 24, 2026
1a2a7e9
fix build issue
mvadari Jun 25, 2026
88ae2bb
pass by reference
mvadari Jun 26, 2026
bcb3de1
Merge branch 'xrplf/sponsor' of https://github.com/XRPLF/rippled into…
mvadari Jun 26, 2026
00fc081
implement the rest of it
mvadari Jun 26, 2026
7644970
shrink diff
mvadari Jun 26, 2026
6947d41
add assert
mvadari Jun 26, 2026
b591bfe
fix build
mvadari Jun 26, 2026
02cc200
clang-tidy I hope you get a rock in your shoe
mvadari Jun 26, 2026
d73340e
switch back to value
mvadari Jun 29, 2026
759bd45
Merge branch 'xrplf/sponsor' of https://github.com/XRPLF/rippled into…
mvadari Jun 29, 2026
bf4fa8e
respond to comments
mvadari Jun 29, 2026
0864dfc
roll back now-unneeded changes
mvadari Jun 29, 2026
2759dfb
clang-tidy go get stung by a bee
mvadari Jun 29, 2026
9485c3c
disable copy constructors
mvadari Jun 29, 2026
aee7651
Merge branch 'xrplf/sponsor' into mvadari/sponsor/apply-view-context
mvadari Jun 29, 2026
4a3a247
Revert "disable copy constructors"
mvadari Jun 29, 2026
c710a8a
Merge branch 'xrplf/sponsor' into mvadari/sponsor/apply-view-context
mvadari Jun 29, 2026
b8ae7a2
use reference in helper functions
mvadari Jun 29, 2026
f005879
fix build issues
mvadari Jun 29, 2026
13aff69
missed one
mvadari Jun 29, 2026
ad4abab
Merge branch 'xrplf/sponsor' of https://github.com/XRPLF/rippled into…
mvadari Jun 29, 2026
4395da1
cmon clang-tidy gimme a break
mvadari Jun 29, 2026
8f470b7
switch to &&
mvadari Jun 29, 2026
c7a3abb
f u clang-tidy
mvadari Jun 29, 2026
4cbc050
fix clang-tidy
mvadari Jun 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/xrpl/ledger/ApplyView.h
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,12 @@ class ApplyView : public ReadView
emptyDirDelete(Keylet const& directory);
};

struct ApplyViewContext
{
ApplyView& view;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should disable copy constructors

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this, it doesn't work because we're passing by value not reference so we are copying

@oleks-rip oleks-rip Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to disable copy constructors and pass it by right reference, or forgotten copy can appear somewhere

STTx const& tx;
};
Comment thread
mvadari marked this conversation as resolved.

namespace directory {
/** Helper functions for managing low-level directory operations.
These are not part of the ApplyView interface.
Expand Down
3 changes: 1 addition & 2 deletions include/xrpl/ledger/View.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,7 @@ canWithdraw(ReadView const& view, STTx const& tx);

[[nodiscard]] TER
doWithdraw(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
AccountID const& senderAcct,
AccountID const& dstAcct,
AccountID const& sourceAcct,
Expand Down
23 changes: 11 additions & 12 deletions include/xrpl/ledger/helpers/EscrowHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ namespace xrpl {
template <ValidIssueType T>
TER
escrowUnlockApplyHelper(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
Rate lockedRate,
SLE::ref sleDest,
STAmount const& xrpBalance,
Expand All @@ -32,8 +31,7 @@ escrowUnlockApplyHelper(
template <>
inline TER
escrowUnlockApplyHelper<Issue>(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
Rate lockedRate,
SLE::ref sleDest,
STAmount const& xrpBalance,
Expand All @@ -49,6 +47,7 @@ escrowUnlockApplyHelper<Issue>(
bool const recvLow = issuer > receiver;
bool const senderIssuer = issuer == sender;
bool const receiverIssuer = issuer == receiver;
auto& view = ctx.view;

if (senderIssuer)
return tecINTERNAL; // LCOV_EXCL_LINE
Expand All @@ -59,12 +58,12 @@ escrowUnlockApplyHelper<Issue>(
if (!view.exists(trustLineKey) && createAsset)
{
// Can the account cover the trust line's reserve?
auto const sponsorSle = getTxReserveSponsor(view, tx);
auto const sponsorSle = getTxReserveSponsor({.view = ctx.view, .tx = ctx.tx});
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE

if (auto const ret =
checkInsufficientReserve(view, tx, sleDest, xrpBalance, *sponsorSle, 1, 0, journal);
if (auto const ret = checkInsufficientReserve(
view, ctx.tx, sleDest, xrpBalance, *sponsorSle, 1, 0, journal);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this should be changed too, like getTxReserveSponsor

@mvadari mvadari Jun 29, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, agreed. However, we can't do that in this PR - it currently takes a ReadView because it's called in preclaim in one place, so that needs to be fixed (in a separate PR) first.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do after #7667, possibly in #7661

!isTesSuccess(ret))
{
JLOG(journal.trace()) << "Trust line does not exist. "
Expand Down Expand Up @@ -169,8 +168,7 @@ escrowUnlockApplyHelper<Issue>(
template <>
inline TER
escrowUnlockApplyHelper<MPTIssue>(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
Rate lockedRate,
SLE::ref sleDest,
STAmount const& xrpBalance,
Expand All @@ -183,18 +181,19 @@ escrowUnlockApplyHelper<MPTIssue>(
{
bool const senderIssuer = issuer == sender;
bool const receiverIssuer = issuer == receiver;
auto& view = ctx.view;

auto const mptID = amount.get<MPTIssue>().getMptID();
auto const issuanceKey = keylet::mptIssuance(mptID);
auto const mptKeylet = keylet::mptoken(issuanceKey.key, receiver);
if (!view.exists(mptKeylet) && createAsset && !receiverIssuer)
{
auto const sponsorSle = getTxReserveSponsor(view, tx);
auto const sponsorSle = getTxReserveSponsor({.view = ctx.view, .tx = ctx.tx});
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE

if (auto const ret =
checkInsufficientReserve(view, tx, sleDest, xrpBalance, *sponsorSle, 1, 0, journal);
if (auto const ret = checkInsufficientReserve(
view, ctx.tx, sleDest, xrpBalance, *sponsorSle, 1, 0, journal);
!isTesSuccess(ret))
return ret;

Expand Down
12 changes: 4 additions & 8 deletions include/xrpl/ledger/helpers/MPTokenHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ canAddHolding(ReadView const& view, MPTIssue const& mptIssue);

[[nodiscard]] TER
authorizeMPToken(
ApplyView& view,
Comment thread
mvadari marked this conversation as resolved.
STTx const& tx,
ApplyViewContext const& ctx,
XRPAmount const& priorBalance,
MPTID const& mptIssuanceID,
AccountID const& account,
Expand Down Expand Up @@ -103,8 +102,7 @@ requireAuth(
*/
[[nodiscard]] TER
enforceMPTokenAuthorization(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
MPTID const& mptIssuanceID,
AccountID const& account,
XRPAmount const& priorBalance,
Expand Down Expand Up @@ -190,17 +188,15 @@ canMPTTradeAndTransfer(

[[nodiscard]] TER
addEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
AccountID const& accountID,
XRPAmount priorBalance,
MPTIssue const& mptIssue,
beast::Journal journal);

[[nodiscard]] TER
removeEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
AccountID const& accountID,
MPTIssue const& mptIssue,
beast::Journal journal);
Expand Down
5 changes: 2 additions & 3 deletions include/xrpl/ledger/helpers/RippleStateHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,16 +229,15 @@ 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 const& ctx,
AccountID const& accountID,
XRPAmount priorBalance,
Issue const& issue,
beast::Journal journal);

[[nodiscard]] TER
removeEmptyHolding(
ApplyView& view,
ApplyViewContext const& ctx,
AccountID const& accountID,
Issue const& issue,
beast::Journal journal);
Expand Down
6 changes: 3 additions & 3 deletions include/xrpl/ledger/helpers/SponsorHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ getTxReserveSponsorAccountID(STTx const& tx)
}

inline std::expected<SLE::pointer, TER>
getTxReserveSponsor(ApplyView& view, STTx const& tx)
getTxReserveSponsor(ApplyViewContext const& ctx)
{
auto const sponsorID = getTxReserveSponsorAccountID(tx);
auto const sponsorID = getTxReserveSponsorAccountID(ctx.tx);
if (sponsorID)
Comment thread
mvadari marked this conversation as resolved.
{
auto sle = view.peek(keylet::account(*sponsorID));
auto sle = ctx.view.peek(keylet::account(*sponsorID));

// already checked in Transactor::checkSponsor
if (!sle)
Expand Down
6 changes: 2 additions & 4 deletions include/xrpl/ledger/helpers/TokenHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,17 +230,15 @@ canAddHolding(ReadView const& view, Asset const& asset);

[[nodiscard]] TER
addEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
AccountID const& accountID,
XRPAmount priorBalance,
Comment thread
mvadari marked this conversation as resolved.
Asset const& asset,
beast::Journal journal);

[[nodiscard]] TER
removeEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
AccountID const& accountID,
Asset const& asset,
beast::Journal journal);
Expand Down
7 changes: 7 additions & 0 deletions include/xrpl/tx/ApplyContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ class ApplyContext
TER
checkInvariants(TER const result, XRPAmount const fee);

ApplyViewContext
getApplyViewContext()
{
XRPL_ASSERT(view_.has_value(), "Previous view exists");
return {.view = *view_, .tx = tx};
}

private:
static TER
failInvariantCheck(TER const result);
Expand Down
2 changes: 1 addition & 1 deletion include/xrpl/tx/transactors/token/MPTokenIssuanceCreate.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class MPTokenIssuanceCreate : public Transactor
beast::Journal const& j) override;

static std::expected<MPTID, TER>
create(ApplyView& view, STTx const& tx, beast::Journal journal, MPTCreateArgs const& args);
create(ApplyViewContext const& ctx, beast::Journal journal, MPTCreateArgs const& args);
};

} // namespace xrpl
17 changes: 9 additions & 8 deletions src/libxrpl/ledger/View.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,7 @@ canWithdraw(ReadView const& view, STTx const& tx)

TER
doWithdraw(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
AccountID const& senderAcct,
AccountID const& dstAcct,
AccountID const& sourceAcct,
Expand All @@ -444,20 +443,21 @@ 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(
{.view = ctx.view, .tx = ctx.tx}, 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,
Expand All @@ -470,13 +470,14 @@ doWithdraw(
// LCOV_EXCL_STOP
}

auto const sponsorSle = getTxReserveSponsor(view, tx);
auto const sponsorSle = getTxReserveSponsor({.view = ctx.view, .tx = ctx.tx});
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
Expand Down
30 changes: 14 additions & 16 deletions src/libxrpl/ledger/helpers/MPTokenHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -126,14 +125,14 @@ canAddHolding(ReadView const& view, MPTIssue const& mptIssue)

[[nodiscard]] TER
addEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
AccountID const& accountID,
XRPAmount priorBalance,
MPTIssue const& mptIssue,
beast::Journal journal)
{
auto const& mptID = mptIssue.getMptID();
auto& view = ctx.view;
auto const mpt = view.peek(keylet::mptIssuance(mptID));
if (!mpt)
return tefINTERNAL; // LCOV_EXCL_LINE
Expand All @@ -144,20 +143,21 @@ addEmptyHolding(
if (accountID == mptIssue.getIssuer())
return tesSUCCESS;

return authorizeMPToken(view, tx, priorBalance, mptID, accountID, journal);
return authorizeMPToken(
{.view = ctx.view, .tx = ctx.tx}, priorBalance, mptID, accountID, journal);
}

[[nodiscard]] TER
authorizeMPToken(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
XRPAmount const& priorBalance,
MPTID const& mptIssuanceID,
AccountID const& account,
beast::Journal journal,
std::uint32_t flags,
std::optional<AccountID> holderID)
{
auto& view = ctx.view;
auto const sleAcct = view.peek(keylet::account(account));
if (!sleAcct)
return tecINTERNAL; // LCOV_EXCL_LINE
Expand Down Expand Up @@ -193,7 +193,7 @@ authorizeMPToken(
// - add the new mptokenKey to the owner directory
// - create the MPToken object for the holder

auto const sponsorSle = getTxReserveSponsor(view, tx);
auto const sponsorSle = getTxReserveSponsor({.view = ctx.view, .tx = ctx.tx});
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE

Expand All @@ -208,7 +208,7 @@ authorizeMPToken(
if (*sponsorSle || ownerCount(sleAcct, journal) >= 2)
{
if (auto const ret = checkInsufficientReserve(
view, tx, sleAcct, priorBalance, *sponsorSle, 1, 0, journal);
view, ctx.tx, sleAcct, priorBalance, *sponsorSle, 1, 0, journal);
!isTesSuccess(ret))
return ret;
}
Expand Down Expand Up @@ -280,8 +280,7 @@ authorizeMPToken(

[[nodiscard]] TER
removeEmptyHolding(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
AccountID const& accountID,
MPTIssue const& mptIssue,
beast::Journal journal)
Expand All @@ -291,6 +290,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& view = ctx.view;
auto const mptoken = view.peek(keylet::mptoken(mptID, accountID));
if (!mptoken)
return accountIsIssuer ? (TER)tesSUCCESS : (TER)tecOBJECT_NOT_FOUND;
Expand All @@ -303,8 +303,7 @@ removeEmptyHolding(
return tecHAS_OBLIGATIONS;

return authorizeMPToken(
view,
tx,
{.view = ctx.view, .tx = ctx.tx},
{}, // priorBalance
mptID,
accountID,
Expand Down Expand Up @@ -413,13 +412,13 @@ requireAuth(

[[nodiscard]] TER
enforceMPTokenAuthorization(
ApplyView& view,
STTx const& tx,
ApplyViewContext const& ctx,
MPTID const& mptIssuanceID,
AccountID const& account,
XRPAmount const& priorBalance, // for MPToken authorization
beast::Journal j)
{
auto& view = ctx.view;
auto const sleIssuance = view.read(keylet::mptIssuance(mptIssuanceID));
if (!sleIssuance)
return tefINTERNAL; // LCOV_EXCL_LINE
Expand Down Expand Up @@ -495,8 +494,7 @@ enforceMPTokenAuthorization(
maybeDomainID.has_value() && sleToken == nullptr,
"xrpl::enforceMPTokenAuthorization : new MPToken for domain");
if (auto const err = authorizeMPToken(
view,
tx,
{.view = ctx.view, .tx = ctx.tx},
priorBalance, // priorBalance
mptIssuanceID, // mptIssuanceID
account, // account
Expand Down
Loading
Loading