1#include <xrpl/tx/transactors/token/MPTokenIssuanceSet.h>
3#include <xrpl/beast/utility/Journal.h>
4#include <xrpl/beast/utility/Zero.h>
5#include <xrpl/beast/utility/instrumentation.h>
6#include <xrpl/core/ServiceRegistry.h>
7#include <xrpl/ledger/ReadView.h>
8#include <xrpl/protocol/ConfidentialTransfer.h>
9#include <xrpl/protocol/Feature.h>
10#include <xrpl/protocol/Indexes.h>
11#include <xrpl/protocol/LedgerFormats.h>
12#include <xrpl/protocol/Permissions.h>
13#include <xrpl/protocol/Protocol.h>
14#include <xrpl/protocol/SField.h>
15#include <xrpl/protocol/STLedgerEntry.h>
16#include <xrpl/protocol/STTx.h>
17#include <xrpl/protocol/TER.h>
18#include <xrpl/protocol/TxFlags.h>
19#include <xrpl/protocol/XRPAmount.h>
20#include <xrpl/tx/Transactor.h>
38 return tfMPTokenIssuanceSetMask;
46 auto const metadata = ctx.
tx[~sfMPTokenMetadata];
47 auto const transferFee = ctx.
tx[~sfTransferFee];
48 auto const immutableFlags = ctx.
tx[~sfImmutableFlags];
49 auto const isMutate = (enableFlags != 0u) || metadata || transferFee || immutableFlags;
50 auto const hasIssuerElGamalKey = ctx.
tx.
isFieldPresent(sfIssuerEncryptionKey);
51 auto const hasAuditorElGamalKey = ctx.
tx.
isFieldPresent(sfAuditorEncryptionKey);
53 bool const enablePrivacy = (enableFlags & tfMPTSetCanHoldConfidentialBalance) != 0u;
60 bool const setConfidentialBalanceImmutable =
62 if ((hasIssuerElGamalKey || hasAuditorElGamalKey || enablePrivacy ||
63 setConfidentialBalanceImmutable) &&
67 if (hasDomain && hasHolder)
70 if (enablePrivacy && hasHolder)
77 auto const accountID = ctx.
tx[sfAccount];
78 auto const holderID = ctx.
tx[~sfHolder];
79 if (holderID && accountID == holderID)
86 if (txFlags == 0 && !hasDomain && !hasIssuerElGamalKey && !hasAuditorElGamalKey &&
94 if (isMutate && holderID)
105 if (transferFee && *transferFee > 0u && enablePrivacy)
113 if (immutableFlags &&
114 ((*immutableFlags == 0u) ||
119 if (hasHolder && (hasIssuerElGamalKey || hasAuditorElGamalKey))
122 if (hasAuditorElGamalKey && !hasIssuerElGamalKey)
142 if (!sleMptIssuance->isFlag(lsfMPTCanLock))
157 if ((*sleMptIssuance)[sfIssuer] != ctx.
tx[sfAccount])
160 if (
auto const holderID = ctx.
tx[~sfHolder])
171 if (
auto const domain = ctx.
tx[~sfDomainID])
173 if (not sleMptIssuance->isFlag(lsfMPTRequireAuth))
186 auto const currentImmutableFlags = sleMptIssuance->getFieldU32(sfImmutableFlags);
188 auto isImmutable = [&](
std::uint32_t flag) ->
bool {
return currentImmutableFlags & flag; };
191 if (enableFlags != 0u)
195 return isImmutable(f.immutableFlag) && ctx.
tx.
isFlag(f.setFlag);
203 if (
auto const fee = ctx.
tx[~sfTransferFee])
208 if (fee > 0u && !sleMptIssuance->isFlag(lsfMPTCanTransfer) &&
209 (enableFlags & tfMPTSetCanTransfer) == 0u)
214 if (fee > 0u && sleMptIssuance->isFlag(lsfMPTCanHoldConfidentialBalance))
224 sleMptIssuance->isFieldPresent(sfIssuerEncryptionKey))
231 sleMptIssuance->isFieldPresent(sfAuditorEncryptionKey))
236 auto const enablesConfidentialBalance =
237 (enableFlags & tfMPTSetCanHoldConfidentialBalance) != 0u;
238 if (enablesConfidentialBalance && sleMptIssuance->isFieldPresent(sfTransferFee) &&
239 (*sleMptIssuance)[sfTransferFee] > 0u)
245 !sleMptIssuance->isFlag(lsfMPTCanHoldConfidentialBalance) && !enablesConfidentialBalance)
251 !sleMptIssuance->isFlag(lsfMPTCanHoldConfidentialBalance) && !enablesConfidentialBalance)
258 ctx.
tx.
isFieldPresent(sfAuditorEncryptionKey) || enablesConfidentialBalance) &&
259 (*sleMptIssuance)[~sfConfidentialOutstandingAmount].value_or(0) > 0)
270 auto const mptIssuanceID =
ctx_.tx[sfMPTokenIssuanceID];
271 auto const holderID =
ctx_.tx[~sfHolder];
272 auto const domainID =
ctx_.tx[~sfDomainID];
290 if (
ctx_.tx.isFlag(tfMPTLock))
292 flagsOut |= lsfMPTLocked;
294 else if (
ctx_.tx.isFlag(tfMPTUnlock))
296 flagsOut &= ~lsfMPTLocked;
304 if (
ctx_.tx.isFlag(f.setFlag))
306 flagsOut |= f.ledgerFlag;
311 if (flagsIn != flagsOut)
312 sle->setFieldU32(sfFlags, flagsOut);
314 if (
auto const immutableFlags =
ctx_.tx[~sfImmutableFlags])
325 sle->getType() == ltMPTOKEN_ISSUANCE,
326 "MPTokenIssuanceSet::doApply : modifying MPTokenIssuance");
328 if (sle->getType() != ltMPTOKEN_ISSUANCE)
331 (*sle)[sfImmutableFlags] = (*sle)[sfImmutableFlags] | *immutableFlags;
334 if (
auto const transferFee =
ctx_.tx[~sfTransferFee])
340 if (transferFee == 0)
342 sle->makeFieldAbsent(sfTransferFee);
346 sle->setFieldU16(sfTransferFee, *transferFee);
350 if (
auto const metadata =
ctx_.tx[~sfMPTokenMetadata])
352 if (metadata->empty())
354 sle->makeFieldAbsent(sfMPTokenMetadata);
358 sle->setFieldVL(sfMPTokenMetadata, *metadata);
366 sle->getType() == ltMPTOKEN_ISSUANCE,
367 "MPTokenIssuanceSet::doApply : modifying MPTokenIssuance");
371 sle->setFieldH256(sfDomainID, *domainID);
375 if (sle->isFieldPresent(sfDomainID))
376 sle->makeFieldAbsent(sfDomainID);
380 if (
auto const pubKey =
ctx_.tx[~sfIssuerEncryptionKey])
384 sle->getType() == ltMPTOKEN_ISSUANCE,
385 "MPTokenIssuanceSet::doApply : modifying MPTokenIssuance");
387 sle->setFieldVL(sfIssuerEncryptionKey, *pubKey);
390 if (
auto const pubKey =
ctx_.tx[~sfAuditorEncryptionKey])
394 sle->getType() == ltMPTOKEN_ISSUANCE,
395 "MPTokenIssuanceSet::doApply : modifying MPTokenIssuance");
397 sle->setFieldVL(sfAuditorEncryptionKey, *pubKey);
A generic endpoint for log messages.
virtual SLE::pointer peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual void update(SLE::ref sle)=0
Indicate changes to a peeked SLE.
static NotTEC preflight(PreflightContext const &ctx)
static bool checkExtraFeatures(PreflightContext const &ctx)
bool finalizeInvariants(STTx const &tx, TER result, XRPAmount fee, ReadView const &view, beast::Journal const &j) override
Check transaction-specific post-conditions after all entries have been visited.
void visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override
Inspect a single ledger entry modified by this transaction.
static TER preclaim(PreclaimContext const &ctx)
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
static constexpr std::array< FlagMapping, 7 > flagMapping
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
std::shared_ptr< STLedgerEntry > pointer
std::shared_ptr< STLedgerEntry const > const & const_ref
bool isFlag(std::uint32_t) const
bool isFieldPresent(SField const &field) const
std::uint32_t getFlags() const
Keylet permissionedDomain(AccountID const &account, SeqProxy const &seq) noexcept
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet mptokenIssuance(MPTID const &issuanceID) noexcept
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool isValidCompressedECPoint(Slice const &buffer)
Verifies that a buffer contains a valid, parsable compressed EC point.
TERSubset< CanCvtToNotTEC > NotTEC
constexpr FlagValue tfMPTokenIssuanceSetEnableFlagMask
constexpr std::size_t kMaxMpTokenMetadataLength
The maximum length of MPTokenMetadata.
constexpr FlagValue tifMPTokenIssuanceImmutableMask
constexpr std::uint16_t kMaxTransferFee
The maximum token transfer fee allowed.
constexpr FlagValue tifMPTCanHoldConfidentialBalance
constexpr std::uint32_t lsifMPTMetadata
TERSubset< CanCvtToTER > TER
constexpr std::uint32_t lsifMPTTransferFee
State information when determining if a tx is likely to claim a fee.
State information when preflighting a tx.