mirror of
https://github.com/XRPLF/rippled.git
synced 2026-10-11 14:18:07 +00:00
Compare commits
11 Commits
nb-counted
...
mvadari/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01a21f5fb8 | ||
|
|
86bc544d7d | ||
|
|
5e2e5bf4e8 | ||
|
|
7f0ce98820 | ||
|
|
1b8074cb41 | ||
|
|
11a9ae0eb6 | ||
|
|
ac380ea18b | ||
|
|
b1903290a4 | ||
|
|
a057e3de26 | ||
|
|
a65d559516 | ||
|
|
2d1818ed97 |
@@ -8,8 +8,12 @@
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
template <typename ViewT>
|
||||
@@ -47,6 +51,59 @@ 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if @p account cannot send or receive tokens of this
|
||||
* MPToken's issuance because a freeze applies: the issuance is globally
|
||||
* locked, this MPToken is individually locked, or (for a vault share)
|
||||
* the vault pseudo-account's underlying asset is frozen.
|
||||
*
|
||||
* The issuance is read once for the global-freeze and vault checks.
|
||||
*
|
||||
* @param account The holder of this MPToken.
|
||||
* @param depth Current recursion depth for the vault-share walk.
|
||||
* @return true if @p account is frozen out of this MPToken's issuance
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
isFrozen(AccountID const& account, std::uint8_t depth = 0) const;
|
||||
|
||||
/**
|
||||
* Creates the MPToken of @p account for @p mptIssuanceID: links it into
|
||||
* the owner directory, sets its fields and sponsor, and inserts it.
|
||||
*
|
||||
* Does not change the owner count.
|
||||
*
|
||||
* @param view The apply view to create the MPToken in.
|
||||
* @param mptIssuanceID The issuance this MPToken is for.
|
||||
* @param account The holder to create the MPToken for.
|
||||
* @param sponsorSle The sponsor to record on the MPToken, or nullptr.
|
||||
* @param flags The flags to set on the new MPToken.
|
||||
* @return tesSUCCESS, or tecDIR_FULL if the owner directory is full
|
||||
*/
|
||||
[[nodiscard]] static TER
|
||||
create(
|
||||
ApplyView& view,
|
||||
MPTID const& mptIssuanceID,
|
||||
AccountID const& account,
|
||||
SLE::Ref sponsorSle,
|
||||
std::uint32_t flags)
|
||||
requires Base::kIsWritable;
|
||||
};
|
||||
|
||||
using MPTokenEntryR = MPTokenEntry<ReadView>;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/ApplyView.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>
|
||||
@@ -213,7 +214,7 @@ escrowUnlockApplyHelper<MPTIssue>(
|
||||
!isTesSuccess(ret))
|
||||
return ret;
|
||||
|
||||
if (auto const ter = createMPToken(ctx.view, mptID, receiver, *sponsorSle, 0);
|
||||
if (auto const ter = MPTokenEntryW::create(ctx.view, mptID, receiver, *sponsorSle, 0);
|
||||
!isTesSuccess(ter))
|
||||
{
|
||||
return ter; // LCOV_EXCL_LINE
|
||||
|
||||
@@ -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
|
||||
@@ -282,14 +279,6 @@ unlockEscrowMPT(
|
||||
STAmount const& grossAmount,
|
||||
beast::Journal j);
|
||||
|
||||
TER
|
||||
createMPToken(
|
||||
ApplyView& view,
|
||||
MPTID const& mptIssuanceID,
|
||||
AccountID const& account,
|
||||
SLE::Ref sponsorSle,
|
||||
std::uint32_t const flags);
|
||||
|
||||
TER
|
||||
checkCreateMPT(
|
||||
xrpl::ApplyView& view,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
78
src/libxrpl/ledger/entries/MPTokenEntry.cpp
Normal file
78
src/libxrpl/ledger/entries/MPTokenEntry.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#include <xrpl/ledger/entries/MPTokenEntry.h>
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/SponsorHelpers.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
template <typename ViewT>
|
||||
bool
|
||||
MPTokenEntry<ViewT>::isFrozen(AccountID const& account, std::uint8_t depth) const
|
||||
{
|
||||
auto const& view = this->readView();
|
||||
auto const& sle = **this;
|
||||
|
||||
XRPL_ASSERT(sle[sfAccount] == account, "xrpl::MPTokenEntry::isFrozen : valid MPToken holder");
|
||||
|
||||
MPTID const mptID = sle[sfMPTokenIssuanceID];
|
||||
auto const issuanceSle = view.read(keylet::mptokenIssuance(mptID));
|
||||
|
||||
if ((issuanceSle && isGlobalFrozen(*issuanceSle)) || sle.isFlag(lsfMPTLocked))
|
||||
return true;
|
||||
|
||||
if (issuanceSle)
|
||||
return isVaultPseudoAccountFrozen(view, account, *issuanceSle, depth);
|
||||
|
||||
return isVaultPseudoAccountFrozen(view, account, MPTIssue{mptID}, depth);
|
||||
}
|
||||
|
||||
template <typename ViewT>
|
||||
TER
|
||||
MPTokenEntry<ViewT>::create(
|
||||
ApplyView& view,
|
||||
MPTID const& mptIssuanceID,
|
||||
AccountID const& account,
|
||||
SLE::Ref sponsorSle,
|
||||
std::uint32_t flags)
|
||||
requires Base::kIsWritable
|
||||
{
|
||||
MPTokenEntry mptoken(mptIssuanceID, account, view);
|
||||
|
||||
auto const ownerNode =
|
||||
view.dirInsert(keylet::ownerDir(account), mptoken.keylet(), describeOwnerDir(account));
|
||||
|
||||
if (!ownerNode)
|
||||
return tecDIR_FULL; // LCOV_EXCL_LINE
|
||||
|
||||
mptoken.newSLE();
|
||||
(*mptoken)[sfAccount] = account;
|
||||
(*mptoken)[sfMPTokenIssuanceID] = mptIssuanceID;
|
||||
(*mptoken)[sfFlags] = flags;
|
||||
(*mptoken)[sfOwnerNode] = *ownerNode;
|
||||
|
||||
addSponsorToLedgerEntry(mptoken.mutableRawSle(), sponsorSle);
|
||||
|
||||
mptoken.insert();
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
template class MPTokenEntry<ReadView>;
|
||||
template class MPTokenEntry<ApplyView>;
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/Sandbox.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
#include <xrpl/ledger/entries/MPTokenEntry.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/protocol/AMMCore.h>
|
||||
@@ -633,8 +633,8 @@ 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));
|
||||
sle && !isFrozen(view, ammAccountID, *sle))
|
||||
if (auto const sle = MPTokenEntryR(issue, ammAccountID, view);
|
||||
sle && !sle.isFrozen(ammAccountID))
|
||||
return STAmount{issue, (*sle)[sfMPTAmount]};
|
||||
return STAmount{asset};
|
||||
},
|
||||
@@ -725,7 +725,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)
|
||||
{
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
#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>
|
||||
#include <xrpl/ledger/helpers/SponsorHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
@@ -58,19 +58,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,
|
||||
@@ -91,18 +83,9 @@ isFrozen(ReadView const& view, AccountID const& account, SLE const& sle, std::ui
|
||||
|
||||
if (sle.getType() == ltMPTOKEN)
|
||||
{
|
||||
XRPL_ASSERT(sle[sfAccount] == account, "xrpl::isFrozen : valid MPToken holder");
|
||||
|
||||
MPTID const mptID = sle[sfMPTokenIssuanceID];
|
||||
auto const issuanceSle = view.read(keylet::mptokenIssuance(mptID));
|
||||
|
||||
if ((issuanceSle && isGlobalFrozen(*issuanceSle)) || isIndividualFrozen(sle))
|
||||
return true;
|
||||
|
||||
if (issuanceSle)
|
||||
return isVaultPseudoAccountFrozen(view, account, *issuanceSle, depth);
|
||||
|
||||
return isVaultPseudoAccountFrozen(view, account, MPTIssue{mptID}, depth);
|
||||
// The entry needs an owning pointer, so this copies the SLE. Callers
|
||||
// that already hold an MPTokenEntry call its isFrozen() directly.
|
||||
return MPTokenEntryR(std::make_shared<SLE const>(sle), view).isFrozen(account, depth);
|
||||
}
|
||||
|
||||
MPTIssue const mptIssue{sle[sfSequence], sle[sfIssuer]};
|
||||
@@ -188,7 +171,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 +203,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 +213,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 +256,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 +285,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 +308,7 @@ authorizeMPToken(
|
||||
if (flagsIn != flagsOut)
|
||||
sleMpt->setFieldU32(sfFlags, flagsOut);
|
||||
|
||||
ctx.view.update(sleMpt);
|
||||
sleMpt.update();
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
@@ -340,7 +324,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 +420,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 +479,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 +495,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 +518,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 +539,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 +716,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 +755,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 +846,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 +865,7 @@ unlockEscrowMPT(
|
||||
} // LCOV_EXCL_STOP
|
||||
|
||||
(*sle)[sfMPTAmount] += delta;
|
||||
view.update(sle);
|
||||
sle.update();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -912,8 +892,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 +925,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
|
||||
@@ -970,35 +949,6 @@ unlockEscrowMPT(
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
createMPToken(
|
||||
ApplyView& view,
|
||||
MPTID const& mptIssuanceID,
|
||||
AccountID const& account,
|
||||
SLE::Ref sponsorSle,
|
||||
std::uint32_t const flags)
|
||||
{
|
||||
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
|
||||
|
||||
auto const ownerNode =
|
||||
view.dirInsert(keylet::ownerDir(account), mptokenKey, describeOwnerDir(account));
|
||||
|
||||
if (!ownerNode)
|
||||
return tecDIR_FULL; // LCOV_EXCL_LINE
|
||||
|
||||
auto mptoken = std::make_shared<SLE>(mptokenKey);
|
||||
(*mptoken)[sfAccount] = account;
|
||||
(*mptoken)[sfMPTokenIssuanceID] = mptIssuanceID;
|
||||
(*mptoken)[sfFlags] = flags;
|
||||
(*mptoken)[sfOwnerNode] = *ownerNode;
|
||||
|
||||
addSponsorToLedgerEntry(mptoken, sponsorSle);
|
||||
|
||||
view.insert(mptoken);
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
checkCreateMPT(
|
||||
xrpl::ApplyView& view,
|
||||
@@ -1015,7 +965,8 @@ checkCreateMPT(
|
||||
auto const mptokenID = keylet::mptoken(mptIssuanceID.key, holder);
|
||||
if (!view.exists(mptokenID))
|
||||
{
|
||||
if (auto const err = createMPToken(view, mptIssue.getMptID(), holder, sponsorSle, flags);
|
||||
if (auto const err =
|
||||
MPTokenEntryW::create(view, mptIssue.getMptID(), holder, sponsorSle, flags);
|
||||
!isTesSuccess(err))
|
||||
{
|
||||
return err;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,10 +437,9 @@ 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)))
|
||||
if (!sleMpt || (zeroIfFrozen == FreezeHandling::ZeroIfFrozen && sleMpt.isFrozen(account)))
|
||||
{
|
||||
amount.clear(mptIssue);
|
||||
}
|
||||
@@ -1238,15 +1238,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 +1267,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 +1278,7 @@ directSendNoFeeMPT(
|
||||
}
|
||||
view.creditHookMPT(uSenderID, uReceiverID, saAmount, (*sle)[sfMPTAmount], available);
|
||||
(*sle)[sfMPTAmount] += amt;
|
||||
view.update(sle);
|
||||
sle.update();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -5,6 +5,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/AMMHelpers.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
@@ -330,7 +331,7 @@ applyCreate(ApplyContext& ctx, Sandbox& sb, AccountID const& account, beast::Jou
|
||||
return err;
|
||||
}
|
||||
|
||||
if (auto const err = createMPToken(sb, mptID, accountId, {}, flags);
|
||||
if (auto const err = MPTokenEntryW::create(sb, mptID, accountId, {}, flags);
|
||||
!isTesSuccess(err))
|
||||
return err;
|
||||
// Don't adjust AMM owner count.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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_);
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <xrpl/ledger/entries/XChainOwnedClaimIDEntry.h> // IWYU pragma: keep
|
||||
#include <xrpl/ledger/entries/XChainOwnedCreateAccountClaimIDEntry.h> // IWYU pragma: keep
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/Keylet.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
@@ -76,12 +77,22 @@ template class SLEBase<ApplyView>;
|
||||
#pragma push_macro("LEDGER_ENTRY")
|
||||
#undef LEDGER_ENTRY
|
||||
|
||||
// No explicit instantiation here, neither a definition nor a declaration.
|
||||
// A definition would instantiate an entry a second time once its member
|
||||
// bodies live in its own .cpp (MSVC rejects that with C4661 under /WX), and a
|
||||
// declaration (`extern template`) stops clang from emitting the inline
|
||||
// constructors of the header-only entries at -O0, which leaves them undefined
|
||||
// at link time in the debug builds. Naming the class in a static_assert is
|
||||
// enough to instantiate its definition, which is all this exhaustiveness
|
||||
// check needs; the per-type suites exercise the members.
|
||||
#define LEDGER_ENTRY(tag, value, name, ...) \
|
||||
template class name##Entry<ReadView>; \
|
||||
template class name##Entry<ApplyView>; \
|
||||
static_assert( \
|
||||
name##Entry<ReadView>::kEntryType == tag && name##Entry<ApplyView>::kEntryType == tag, \
|
||||
#name "Entry must be bound to " #tag);
|
||||
#name "Entry must be bound to " #tag); \
|
||||
static_assert( \
|
||||
std::is_constructible_v<name##Entry<ReadView>, Keylet const&, ReadView const&> && \
|
||||
std::is_constructible_v<name##Entry<ApplyView>, Keylet const&, ApplyView&>, \
|
||||
#name "Entry must be constructible from a Keylet and a view");
|
||||
|
||||
#include <xrpl/protocol/detail/ledger_entries.macro>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user