Compare commits

...

4 Commits

Author SHA1 Message Date
Mayukha Vadari
b1903290a4 Document isIndividualFrozen return value 2026-10-05 15:44:53 +01:00
Mayukha Vadari
a057e3de26 refactor: Move isIndividualFrozen onto MPTokenEntry
Replace the free isIndividualFrozen(MPTokenEntryR const&) overload with
a const member MPTokenEntry::isIndividualFrozen(). The
(view, account, MPTIssue) free function stays and now calls the member.

Pure refactor, no behavior change.
2026-10-05 13:57:32 +01:00
Mayukha Vadari
a65d559516 refactor: Use MPTokenEntry in ConfidentialMPTHolderKeyUpdate
Develop added ConfidentialMPTHolderKeyUpdate (#8266) after this PR was
opened. Migrate its MPToken read and peek to MPTokenEntryR and
MPTokenEntryW so the PR still covers every MPToken pointer site.

Pure refactor: no behavior change.
2026-10-05 13:57:03 +01:00
Mayukha Vadari
2d1818ed97 refactor: Use MPTokenEntry everywhere
Replace raw MPToken (ltMPTOKEN) SLE pointers with MPTokenEntryR and
MPTokenEntryW in the ledger helpers and transactors. Helpers that take
an MPToken SLE (isIndividualFrozen, deleteAMMMPToken, and the
static proof helpers in ConfidentialMPTConvertBack and
ConfidentialMPTSend) now take the wrapper instead. They stay free
functions.

MPTokenIssuance pointers, and parameters that accept either an
MPToken or an MPTokenIssuance (isFrozen, assetOfHolding, the
MPTokenIssuanceSet target SLE), are unchanged.

Pure refactor: no behavior change.
2026-10-05 13:32:46 +01:00
17 changed files with 108 additions and 96 deletions

View File

@@ -47,6 +47,22 @@ public:
: Base(keylet::mptoken(mptokenKey), view, j)
{
}
/**
* Returns true if this MPToken carries the individual-lock flag
* (lsfMPTLocked).
*
* @warning This checks only the raw per-holder lock bit. It does not
* perform the transitive vault pseudo-account check. Use isFrozen() to
* decide whether the holder may send or receive tokens.
*
* @return true if lsfMPTLocked is set on this MPToken
*/
[[nodiscard]] bool
isIndividualFrozen() const
{
return (*this)->isFlag(lsfMPTLocked);
}
};
using MPTokenEntryR = MPTokenEntry<ReadView>;

View File

@@ -47,9 +47,6 @@ isGlobalFrozen(SLE const& issuanceSle);
[[nodiscard]] bool
isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue);
[[nodiscard]] bool
isIndividualFrozen(SLE const& mptSle);
/**
* Returns true if @p account cannot send or receive tokens of @p mptIssue
* because a freeze applies. This is the complete check callers should use

View File

@@ -4,6 +4,7 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/MPTokenEntry.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/IOUAmount.h>
@@ -275,13 +276,12 @@ deleteAMMTrustLine(
beast::Journal j);
/**
* Delete AMMs MPToken. The passed `sle` must be obtained from a prior
* call to view.peek().
* Delete AMMs MPToken.
*/
[[nodiscard]] TER
deleteAMMMPToken(
ApplyView& view,
SLE::pointer sleMPT,
MPTokenEntryW& sleMPT,
AccountID const& ammAccountID,
beast::Journal j);

View File

@@ -11,6 +11,7 @@
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/MPTokenEntry.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
@@ -633,7 +634,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 (auto const sle = MPTokenEntryR(issue, ammAccountID, view);
sle && !isFrozen(view, ammAccountID, *sle))
return STAmount{issue, (*sle)[sfMPTAmount]};
return STAmount{asset};
@@ -725,7 +726,8 @@ deleteAMMMPTokens(Sandbox& sb, AccountID const& ammAccountID, beast::Journal j)
// LCOV_EXCL_STOP
}
return {deleteAMMMPToken(sb, sleItem, ammAccountID, j), SkipEntry::No};
MPTokenEntryW sleMpt(sleItem->key(), sb, j);
return {deleteAMMMPToken(sb, sleMpt, ammAccountID, j), SkipEntry::No};
}
if (nodeType == ltRIPPLE_STATE)
{

View File

@@ -7,6 +7,7 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/MPTokenEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
@@ -58,19 +59,11 @@ isGlobalFrozen(SLE const& issuanceSle)
bool
isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue)
{
if (auto const sle = view.read(keylet::mptoken(mptIssue.getMptID(), account)))
return isIndividualFrozen(*sle);
if (auto const sle = MPTokenEntryR(mptIssue.getMptID(), account, view))
return sle.isIndividualFrozen();
return false;
}
bool
isIndividualFrozen(SLE const& mptSle)
{
XRPL_ASSERT(mptSle.getType() == ltMPTOKEN, "xrpl::isIndividualFrozen : MPToken SLE");
return mptSle.isFlag(lsfMPTLocked);
}
bool
isFrozen(
ReadView const& view,
@@ -96,7 +89,7 @@ isFrozen(ReadView const& view, AccountID const& account, SLE const& sle, std::ui
MPTID const mptID = sle[sfMPTokenIssuanceID];
auto const issuanceSle = view.read(keylet::mptokenIssuance(mptID));
if ((issuanceSle && isGlobalFrozen(*issuanceSle)) || isIndividualFrozen(sle))
if ((issuanceSle && isGlobalFrozen(*issuanceSle)) || sle.isFlag(lsfMPTLocked))
return true;
if (issuanceSle)
@@ -188,7 +181,7 @@ addEmptyHolding(
// still rejected before the "MPToken already exists" short circuit.
if (mpt->isFlag(lsfMPTLocked))
return tefINTERNAL; // LCOV_EXCL_LINE
if (ctx.view.peek(keylet::mptoken(mptID, accountID)))
if (MPTokenEntryW(mptID, accountID, ctx.view))
return tecDUPLICATE;
if (accountID == mptIssue.getIssuer())
return tesSUCCESS;
@@ -220,8 +213,7 @@ authorizeMPToken(
// - delete the MPToken
if ((flags & tfMPTUnauthorize) != 0u)
{
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
auto const sleMpt = ctx.view.peek(mptokenKey);
MPTokenEntryW sleMpt(mptIssuanceID, account, ctx.view, journal);
if (!sleMpt || (*sleMpt)[sfMPTAmount] != 0 ||
(ctx.view.rules().enabled(fixCleanup3_1_3) &&
(*sleMpt)[~sfLockedAmount].valueOr(0) != 0))
@@ -231,9 +223,9 @@ authorizeMPToken(
keylet::ownerDir(account), (*sleMpt)[sfOwnerNode], sleMpt->key(), false))
return tecINTERNAL; // LCOV_EXCL_LINE
decreaseOwnerCountForObject(ctx.view, sleAcct, sleMpt, 1, journal);
decreaseOwnerCountForObject(ctx.view, sleAcct, sleMpt.mutableRawSle(), 1, journal);
ctx.view.erase(sleMpt);
sleMpt.erase();
return tesSUCCESS;
}
@@ -274,19 +266,21 @@ authorizeMPToken(
// LCOV_EXCL_STOP
}
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
auto mptoken = std::make_shared<SLE>(mptokenKey);
if (auto ter = dirLink(ctx.view, account, mptoken))
MPTokenEntryW mptoken(mptIssuanceID, account, ctx.view, journal);
mptoken.newSLE();
// dirLink takes a non-const SLE::pointer&, so pass a copy of the pointer.
auto mptokenSle = mptoken.mutableRawSle();
if (auto ter = dirLink(ctx.view, account, mptokenSle))
return ter; // LCOV_EXCL_LINE
(*mptoken)[sfAccount] = account;
(*mptoken)[sfMPTokenIssuanceID] = mptIssuanceID;
(*mptoken)[sfFlags] = 0;
ctx.view.insert(mptoken);
mptoken.insert();
// Update owner count.
increaseOwnerCount(ctx.view, sleAcct, sponsorSle, 1, journal);
addSponsorToLedgerEntry(mptoken, sponsorSle);
addSponsorToLedgerEntry(mptoken.mutableRawSle(), sponsorSle);
return tesSUCCESS;
}
@@ -301,7 +295,7 @@ authorizeMPToken(
if (account != (*sleMptIssuance)[sfIssuer])
return tecINTERNAL; // LCOV_EXCL_LINE
auto const sleMpt = ctx.view.peek(keylet::mptoken(mptIssuanceID, *holderID));
MPTokenEntryW sleMpt(mptIssuanceID, *holderID, ctx.view, journal);
if (!sleMpt)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -324,7 +318,7 @@ authorizeMPToken(
if (flagsIn != flagsOut)
sleMpt->setFieldU32(sfFlags, flagsOut);
ctx.view.update(sleMpt);
sleMpt.update();
return tesSUCCESS;
}
@@ -340,7 +334,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 = ctx.view.peek(keylet::mptoken(mptID, accountID));
MPTokenEntryW mptoken(mptID, accountID, ctx.view, journal);
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
@@ -436,8 +430,7 @@ requireAuth(
}
}
auto const mptokenID = keylet::mptoken(mptID.key, account);
auto const sleToken = view.read(mptokenID);
MPTokenEntryR const sleToken(mptID.key, account, view);
// if account has no MPToken, fail
if (!sleToken && (authType == AuthType::StrongAuth || authType == AuthType::Legacy))
@@ -496,8 +489,7 @@ enforceMPTokenAuthorization(
if (account == sleIssuance->at(sfIssuer))
return tefINTERNAL; // LCOV_EXCL_LINE
auto const keylet = keylet::mptoken(mptIssuanceID, account);
auto const sleToken = ctx.view.read(keylet); // NOTE: might be null
MPTokenEntryR const sleToken(mptIssuanceID, account, ctx.view, j); // NOTE: might not exist
auto const maybeDomainID = sleIssuance->at(~sfDomainID);
bool expired = false;
bool const authorizedByDomain = [&]() -> bool {
@@ -513,7 +505,7 @@ enforceMPTokenAuthorization(
return false;
}();
if (!authorizedByDomain && sleToken == nullptr)
if (!authorizedByDomain && !sleToken)
{
// Could not find MPToken and won't create one, could be either of:
//
@@ -536,14 +528,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.exists() && !maybeDomainID.has_value(),
"xrpl::enforceMPTokenAuthorization : found MPToken");
if (sleToken->isFlag(lsfMPTAuthorized))
return tesSUCCESS;
return tecNO_AUTH;
}
if (authorizedByDomain && sleToken != nullptr)
if (authorizedByDomain && sleToken.exists())
{
// Found an MPToken, authorized by the domain. Ignore authorization flag
// lsfMPTAuthorized because it is meaningless. Return tesSUCCESS
@@ -557,7 +549,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.exists(),
"xrpl::enforceMPTokenAuthorization : new MPToken for domain");
if (auto const err = authorizeMPToken(
ctx,
@@ -734,8 +726,7 @@ lockEscrowMPT(ApplyView& view, AccountID const& sender, STAmount const& amount,
// 1. Decrease the MPT Holder MPTAmount
// 2. Increase the MPT Holder EscrowedAmount
{
auto const mptokenID = keylet::mptoken(mptID.key, sender);
auto sle = view.peek(mptokenID);
MPTokenEntryW sle(mptID.key, sender, view, j);
if (!sle)
{ // LCOV_EXCL_START
JLOG(j.error()) << "lockEscrowMPT: MPToken not found for " << sender;
@@ -774,7 +765,7 @@ lockEscrowMPT(ApplyView& view, AccountID const& sender, STAmount const& amount,
sle->setFieldU64(sfLockedAmount, pay);
}
view.update(sle);
sle.update();
}
// 1. Increase the Issuance EscrowedAmount
@@ -865,8 +856,7 @@ unlockEscrowMPT(
if (issuer != receiver)
{
// Increase the MPT Holder MPTAmount
auto const mptokenID = keylet::mptoken(mptID.key, receiver);
auto sle = view.peek(mptokenID);
MPTokenEntryW sle(mptID.key, receiver, view, j);
if (!sle)
{ // LCOV_EXCL_START
JLOG(j.error()) << "unlockEscrowMPT: MPToken not found for " << receiver;
@@ -885,7 +875,7 @@ unlockEscrowMPT(
} // LCOV_EXCL_STOP
(*sle)[sfMPTAmount] += delta;
view.update(sle);
sle.update();
}
else
{
@@ -912,8 +902,7 @@ unlockEscrowMPT(
return tecINTERNAL;
} // LCOV_EXCL_STOP
// Decrease the MPT Holder EscrowedAmount
auto const mptokenID = keylet::mptoken(mptID.key, sender);
auto sle = view.peek(mptokenID);
MPTokenEntryW sle(mptID.key, sender, view, j);
if (!sle)
{ // LCOV_EXCL_START
JLOG(j.error()) << "unlockEscrowMPT: MPToken not found for " << sender;
@@ -946,7 +935,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
@@ -978,23 +967,23 @@ createMPToken(
SLE::Ref sponsorSle,
std::uint32_t const flags)
{
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
MPTokenEntryW mptoken(mptIssuanceID, account, view);
auto const ownerNode =
view.dirInsert(keylet::ownerDir(account), mptokenKey, describeOwnerDir(account));
view.dirInsert(keylet::ownerDir(account), mptoken.keylet(), describeOwnerDir(account));
if (!ownerNode)
return tecDIR_FULL; // LCOV_EXCL_LINE
auto mptoken = std::make_shared<SLE>(mptokenKey);
mptoken.newSLE();
(*mptoken)[sfAccount] = account;
(*mptoken)[sfMPTokenIssuanceID] = mptIssuanceID;
(*mptoken)[sfFlags] = flags;
(*mptoken)[sfOwnerNode] = *ownerNode;
addSponsorToLedgerEntry(mptoken, sponsorSle);
addSponsorToLedgerEntry(mptoken.mutableRawSle(), sponsorSle);
view.insert(mptoken);
mptoken.insert();
return tesSUCCESS;
}

View File

@@ -7,6 +7,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/MPTokenEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -846,7 +847,7 @@ deleteAMMTrustLine(
TER
deleteAMMMPToken(
ApplyView& view,
SLE::pointer sleMpt,
MPTokenEntryW& sleMpt,
AccountID const& ammAccountID,
beast::Journal j)
{
@@ -854,7 +855,7 @@ deleteAMMMPToken(
keylet::ownerDir(ammAccountID), (*sleMpt)[sfOwnerNode], sleMpt->key(), false))
return tefBAD_LEDGER; // LCOV_EXCL_LINE
view.erase(sleMpt);
sleMpt.erase();
return tesSUCCESS;
}

View File

@@ -7,6 +7,7 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/MPTokenEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
@@ -436,7 +437,7 @@ accountHolds(
return view.balanceHookMPT(issuer, mptIssue, available);
}
auto const sleMpt = view.read(keylet::mptoken(mptIssue.getMptID(), account));
MPTokenEntryR const sleMpt(mptIssue.getMptID(), account, view, j);
if (!sleMpt ||
(zeroIfFrozen == FreezeHandling::ZeroIfFrozen && isFrozen(view, account, *sleMpt)))
@@ -1238,15 +1239,14 @@ directSendNoFeeMPT(
}
else
{
auto const mptokenID = keylet::mptoken(mptID.key, uSenderID);
if (auto sle = view.peek(mptokenID))
if (auto sle = MPTokenEntryW(mptID.key, uSenderID, view, j))
{
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
{
@@ -1268,8 +1268,7 @@ directSendNoFeeMPT(
}
else
{
auto const mptokenID = keylet::mptoken(mptID.key, uReceiverID);
if (auto sle = view.peek(mptokenID))
if (auto sle = MPTokenEntryW(mptID.key, uReceiverID, view, j))
{
if (view.rules().enabled(featureMPTokensV2))
{
@@ -1280,7 +1279,7 @@ directSendNoFeeMPT(
}
view.creditHookMPT(uSenderID, uReceiverID, saAmount, (*sle)[sfMPTAmount], available);
(*sle)[sfMPTAmount] += amt;
view.update(sle);
sle.update();
}
else
{

View File

@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/MPTokenEntry.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Indexes.h>
@@ -210,7 +211,7 @@ isSoleShareholder(ReadView const& view, AccountID const& account, SLE::ConstRef
auto const shareMPTID =
makeMptID(issuance->getFieldU32(sfSequence), issuance->getAccountID(sfIssuer));
auto const sleToken = view.read(keylet::mptoken(shareMPTID, account));
MPTokenEntryR const sleToken(shareMPTID, account, view);
if (!sleToken)
return false; // LCOV_EXCL_LINE

View File

@@ -4,6 +4,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/MPTokenEntry.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -94,7 +95,7 @@ ConfidentialMPTClawback::preclaim(PreclaimContext const& ctx)
return tecNO_PERMISSION;
// Check holder's MPToken
auto const sleHolderMPToken = ctx.view.read(keylet::mptoken(mptIssuanceID, holder));
MPTokenEntryR const sleHolderMPToken(mptIssuanceID, holder, ctx.view);
if (!sleHolderMPToken)
return tecOBJECT_NOT_FOUND;
@@ -133,7 +134,7 @@ ConfidentialMPTClawback::doApply()
auto const holder = ctx_.tx[sfHolder];
auto sleIssuance = view().peek(keylet::mptokenIssuance(mptIssuanceID));
auto sleHolderMPToken = view().peek(keylet::mptoken(mptIssuanceID, holder));
MPTokenEntryW sleHolderMPToken(mptIssuanceID, holder, view(), j_);
if (!sleIssuance || !sleHolderMPToken)
{
@@ -228,7 +229,7 @@ ConfidentialMPTClawback::doApply()
return tecINTERNAL; // LCOV_EXCL_LINE
(*sleIssuance)[sfOutstandingAmount] = oldOA - clawAmount;
view().update(sleHolderMPToken);
sleHolderMPToken.update();
view().update(sleIssuance);
return tesSUCCESS;

View File

@@ -6,6 +6,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/MPTokenEntry.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Feature.h>
@@ -108,7 +109,7 @@ ConfidentialMPTConvert::preclaim(PreclaimContext const& ctx)
if (requiresAuditor != hasAuditor)
return tecNO_PERMISSION;
auto const sleMptoken = ctx.view.read(keylet::mptoken(issuanceID, account));
MPTokenEntryR const sleMptoken(issuanceID, account, ctx.view);
if (!sleMptoken)
return tecOBJECT_NOT_FOUND;
@@ -225,7 +226,7 @@ ConfidentialMPTConvert::doApply()
{
auto const mptIssuanceID = ctx_.tx[sfMPTokenIssuanceID];
auto sleMptoken = view().peek(keylet::mptoken(mptIssuanceID, accountID_));
MPTokenEntryW sleMptoken(mptIssuanceID, accountID_, view(), j_);
if (!sleMptoken)
{
// LCOV_EXCL_START
@@ -377,7 +378,7 @@ ConfidentialMPTConvert::doApply()
}
view().update(sleIssuance);
view().update(sleMptoken);
sleMptoken.update();
return tesSUCCESS;
}

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/entries/MPTokenEntry.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Feature.h>
@@ -71,7 +72,7 @@ static TER
verifyProofs(
STTx const& tx,
std::shared_ptr<SLE const> const& issuance,
std::shared_ptr<SLE const> const& mptoken)
MPTokenEntryR const& mptoken)
{
if (!mptoken->isFieldPresent(sfHolderEncryptionKey))
{
@@ -187,7 +188,7 @@ ConfidentialMPTConvertBack::preclaim(PreclaimContext const& ctx)
// LCOV_EXCL_STOP
}
auto const sleMptoken = ctx.view.read(keylet::mptoken(mptIssuanceID, account));
MPTokenEntryR const sleMptoken(mptIssuanceID, account, ctx.view);
if (!sleMptoken)
return tecOBJECT_NOT_FOUND;
@@ -244,7 +245,7 @@ ConfidentialMPTConvertBack::doApply()
{
auto const mptIssuanceID = ctx_.tx[sfMPTokenIssuanceID];
auto sleMptoken = view().peek(keylet::mptoken(mptIssuanceID, accountID_));
MPTokenEntryW sleMptoken(mptIssuanceID, accountID_, view(), j_);
if (!sleMptoken)
{
// LCOV_EXCL_START
@@ -334,7 +335,7 @@ ConfidentialMPTConvertBack::doApply()
incrementConfidentialVersion(*sleMptoken);
view().update(sleIssuance);
view().update(sleMptoken);
sleMptoken.update();
return tesSUCCESS;
}

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/entries/MPTokenEntry.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -116,7 +117,7 @@ ConfidentialMPTHolderKeyUpdate::preclaim(PreclaimContext const& ctx)
if (!sleIssuance->isFlag(lsfMPTCanHoldConfidentialBalance))
return tecNO_PERMISSION;
auto const sleMptoken = ctx.view.read(keylet::mptoken(mptIssuanceID, account));
MPTokenEntryR const sleMptoken(mptIssuanceID, account, ctx.view);
if (!sleMptoken)
return tecOBJECT_NOT_FOUND;
@@ -150,7 +151,7 @@ TER
ConfidentialMPTHolderKeyUpdate::doApply()
{
auto const mptIssuanceID = ctx_.tx[sfMPTokenIssuanceID];
auto sleMptoken = view().peek(keylet::mptoken(mptIssuanceID, accountID_));
MPTokenEntryW sleMptoken(mptIssuanceID, accountID_, view(), j_);
if (!sleMptoken)
{
// LCOV_EXCL_START
@@ -166,7 +167,7 @@ ConfidentialMPTHolderKeyUpdate::doApply()
// The holder revokes their pending recovery authorization; the
// current key and balances are left untouched.
sleMptoken->makeFieldAbsent(sfRecoveryKey);
view().update(sleMptoken);
sleMptoken.update();
return tesSUCCESS;
}
@@ -197,7 +198,7 @@ ConfidentialMPTHolderKeyUpdate::doApply()
// LCOV_EXCL_STOP
}
view().update(sleMptoken);
sleMptoken.update();
return tesSUCCESS;
}

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/entries/MPTokenEntry.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Indexes.h>
@@ -59,8 +60,7 @@ ConfidentialMPTMergeInbox::preclaim(PreclaimContext const& ctx)
// LCOV_EXCL_STOP
}
auto const sleMptoken =
ctx.view.read(keylet::mptoken(ctx.tx[sfMPTokenIssuanceID], ctx.tx[sfAccount]));
MPTokenEntryR const sleMptoken(ctx.tx[sfMPTokenIssuanceID], ctx.tx[sfAccount], ctx.view);
if (!sleMptoken)
return tecOBJECT_NOT_FOUND;
@@ -88,7 +88,7 @@ TER
ConfidentialMPTMergeInbox::doApply()
{
auto const mptIssuanceID = ctx_.tx[sfMPTokenIssuanceID];
auto sleMptoken = view().peek(keylet::mptoken(mptIssuanceID, accountID_));
MPTokenEntryW sleMptoken(mptIssuanceID, accountID_, view(), j_);
if (!sleMptoken)
{
// LCOV_EXCL_START
@@ -147,7 +147,7 @@ ConfidentialMPTMergeInbox::doApply()
incrementConfidentialVersion(*sleMptoken);
view().update(sleMptoken);
sleMptoken.update();
return tesSUCCESS;
}

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/entries/MPTokenEntry.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -131,7 +132,7 @@ ConfidentialMPTMirrorUpdate::preclaim(PreclaimContext const& ctx)
return tecNO_TARGET;
// In either issuer or holder mode, check the existence of the MPToken object.
auto const sleMptoken = ctx.view.read(keylet::mptoken(mptIssuanceID, holderID));
MPTokenEntryR const sleMptoken(mptIssuanceID, holderID, ctx.view);
if (!sleMptoken)
return tecOBJECT_NOT_FOUND;
@@ -224,7 +225,7 @@ ConfidentialMPTMirrorUpdate::doApply()
auto const holder = ctx_.tx[~sfHolder];
auto const holderID = holder.value_or(accountID_);
auto sleMptoken = view().peek(keylet::mptoken(mptIssuanceID, holderID));
MPTokenEntryW sleMptoken(mptIssuanceID, holderID, view(), j_);
if (!sleMptoken)
{
// LCOV_EXCL_START
@@ -250,7 +251,7 @@ ConfidentialMPTMirrorUpdate::doApply()
setAuditorMirrorEpoch(*sleIssuance, *sleMptoken);
}
view().update(sleMptoken);
sleMptoken.update();
return tesSUCCESS;
}

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/entries/MPTokenEntry.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
@@ -100,8 +101,8 @@ namespace detail {
static TER
verifySendProofs(
PreclaimContext const& ctx,
std::shared_ptr<SLE const> const& sleSenderMPToken,
std::shared_ptr<SLE const> const& sleDestinationMPToken,
MPTokenEntryR const& sleSenderMPToken,
MPTokenEntryR const& sleDestinationMPToken,
std::shared_ptr<SLE const> const& sleIssuance)
{
// Sanity check
@@ -222,7 +223,7 @@ ConfidentialMPTSend::preclaim(PreclaimContext const& ctx)
}
// Check sender's MPToken existence
auto const sleSenderMPToken = ctx.view.read(keylet::mptoken(mptIssuanceID, account));
MPTokenEntryR const sleSenderMPToken(mptIssuanceID, account, ctx.view);
if (!sleSenderMPToken)
return tecOBJECT_NOT_FOUND;
@@ -235,7 +236,7 @@ ConfidentialMPTSend::preclaim(PreclaimContext const& ctx)
}
// Check destination's MPToken existence
auto const sleDestinationMPToken = ctx.view.read(keylet::mptoken(mptIssuanceID, destination));
MPTokenEntryR const sleDestinationMPToken(mptIssuanceID, destination, ctx.view);
if (!sleDestinationMPToken)
return tecOBJECT_NOT_FOUND;
@@ -305,8 +306,8 @@ ConfidentialMPTSend::doApply()
auto const mptIssuanceID = ctx_.tx[sfMPTokenIssuanceID];
auto const destination = ctx_.tx[sfDestination];
auto sleSenderMPToken = view().peek(keylet::mptoken(mptIssuanceID, accountID_));
auto sleDestinationMPToken = view().peek(keylet::mptoken(mptIssuanceID, destination));
MPTokenEntryW sleSenderMPToken(mptIssuanceID, accountID_, view(), j_);
MPTokenEntryW sleDestinationMPToken(mptIssuanceID, destination, view(), j_);
auto const sleIssuance = view().read(keylet::mptokenIssuance(mptIssuanceID));
auto const sleDestAcct = view().read(keylet::account(destination));
@@ -469,8 +470,8 @@ ConfidentialMPTSend::doApply()
// increment sender version only; receiver version is not modified by incoming sends
incrementConfidentialVersion(*sleSenderMPToken);
view().update(sleSenderMPToken);
view().update(sleDestinationMPToken);
sleSenderMPToken.update();
sleDestinationMPToken.update();
return tesSUCCESS;
}

View File

@@ -1,6 +1,7 @@
#include <xrpl/tx/transactors/token/MPTokenAuthorize.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/entries/MPTokenEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/protocol/Feature.h>
@@ -47,8 +48,7 @@ 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));
MPTokenEntryR const sleMpt(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

@@ -3,6 +3,7 @@
#include <xrpl/basics/Log.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/ledger/entries/MPTokenEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
@@ -131,7 +132,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 (MPTokenEntryW(shareMPTID, accountID_, view(), j_))
{
if (auto const ter =
removeEmptyHolding(applyViewContext, accountID_, MPTIssue(shareMPTID), j_);