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>
39 return tfMPTokenIssuanceSetMask;
53 .canEnableFlag = lsmfMPTCanEnableCanLock,
54 .ledgerFlag = lsfMPTCanLock},
56 .canEnableFlag = lsmfMPTCanEnableRequireAuth,
57 .ledgerFlag = lsfMPTRequireAuth},
59 .canEnableFlag = lsmfMPTCanEnableCanEscrow,
60 .ledgerFlag = lsfMPTCanEscrow},
62 .canEnableFlag = lsmfMPTCanEnableCanTrade,
63 .ledgerFlag = lsfMPTCanTrade},
65 .canEnableFlag = lsmfMPTCanEnableCanTransfer,
66 .ledgerFlag = lsfMPTCanTransfer},
68 .canEnableFlag = lsmfMPTCanEnableCanClawback,
69 .ledgerFlag = lsfMPTCanClawback}}};
74 auto const mutableFlags = ctx.
tx[~sfMutableFlags];
75 auto const metadata = ctx.
tx[~sfMPTokenMetadata];
76 auto const transferFee = ctx.
tx[~sfTransferFee];
77 auto const isMutate = mutableFlags || metadata || transferFee;
78 auto const hasIssuerElGamalKey = ctx.
tx.
isFieldPresent(sfIssuerEncryptionKey);
79 auto const hasAuditorElGamalKey = ctx.
tx.
isFieldPresent(sfAuditorEncryptionKey);
82 bool const enablePrivacy =
91 if ((hasIssuerElGamalKey || hasAuditorElGamalKey || enablePrivacy) &&
95 if (hasDomain && hasHolder)
98 if (enablePrivacy && hasHolder)
105 auto const accountID = ctx.
tx[sfAccount];
106 auto const holderID = ctx.
tx[~sfHolder];
107 if (holderID && accountID == holderID)
114 if (txFlags == 0 && !hasDomain && !hasIssuerElGamalKey && !hasAuditorElGamalKey &&
122 if (isMutate && holderID)
132 if (transferFee && *transferFee > 0u && enablePrivacy)
145 if (hasHolder && (hasIssuerElGamalKey || hasAuditorElGamalKey))
148 if (hasAuditorElGamalKey && !hasIssuerElGamalKey)
168 if (!sleMptIssuance->isFlag(lsfMPTCanLock))
183 if ((*sleMptIssuance)[sfIssuer] != ctx.
tx[sfAccount])
186 if (
auto const holderID = ctx.
tx[~sfHolder])
197 if (
auto const domain = ctx.
tx[~sfDomainID])
199 if (not sleMptIssuance->isFlag(lsfMPTRequireAuth))
202 if (*domain != beast::kZero)
212 auto const currentMutableFlags = sleMptIssuance->getFieldU32(sfMutableFlags);
214 auto isMutableFlag = [&](
std::uint32_t mutableFlag) ->
bool {
215 return currentMutableFlags & mutableFlag;
218 auto const mutableFlags = ctx.
tx[~sfMutableFlags];
220 bool const enablesConfidentialAmount =
225 return !isMutableFlag(f.canEnableFlag) && ((*mutableFlags & f.setFlag) != 0u);
229 if (enablesConfidentialAmount &&
230 isMutableFlag(lsmfMPTCannotEnableCanHoldConfidentialBalance))
234 if (!isMutableFlag(lsmfMPTCanMutateMetadata) && ctx.
tx.
isFieldPresent(sfMPTokenMetadata))
237 if (
auto const fee = ctx.
tx[~sfTransferFee])
243 if (fee > 0u && !sleMptIssuance->isFlag(lsfMPTCanTransfer))
248 if (fee > 0u && sleMptIssuance->isFlag(lsfMPTCanHoldConfidentialBalance))
251 if (!isMutableFlag(lsmfMPTCanMutateTransferFee))
257 sleMptIssuance->isFieldPresent(sfIssuerEncryptionKey))
264 sleMptIssuance->isFieldPresent(sfAuditorEncryptionKey))
269 if (enablesConfidentialAmount && sleMptIssuance->isFieldPresent(sfTransferFee) &&
270 (*sleMptIssuance)[sfTransferFee] > 0u)
276 !sleMptIssuance->isFlag(lsfMPTCanHoldConfidentialBalance) && !enablesConfidentialAmount)
282 !sleMptIssuance->isFlag(lsfMPTCanHoldConfidentialBalance) && !enablesConfidentialAmount)
289 ctx.
tx.
isFieldPresent(sfAuditorEncryptionKey) || enablesConfidentialAmount) &&
290 (*sleMptIssuance)[~sfConfidentialOutstandingAmount].value_or(0) > 0)
301 auto const mptIssuanceID =
ctx_.tx[sfMPTokenIssuanceID];
302 auto const holderID =
ctx_.tx[~sfHolder];
303 auto const domainID =
ctx_.tx[~sfDomainID];
321 if (
ctx_.tx.isFlag(tfMPTLock))
323 flagsOut |= lsfMPTLocked;
325 else if (
ctx_.tx.isFlag(tfMPTUnlock))
327 flagsOut &= ~lsfMPTLocked;
330 if (
auto const mutableFlags =
ctx_.tx[~sfMutableFlags].value_or(0))
334 if ((mutableFlags & f.setFlag) != 0u)
336 flagsOut |= f.ledgerFlag;
341 flagsOut |= lsfMPTCanHoldConfidentialBalance;
344 if (flagsIn != flagsOut)
345 sle->setFieldU32(sfFlags, flagsOut);
347 if (
auto const transferFee =
ctx_.tx[~sfTransferFee])
353 if (transferFee == 0)
355 sle->makeFieldAbsent(sfTransferFee);
359 sle->setFieldU16(sfTransferFee, *transferFee);
363 if (
auto const metadata =
ctx_.tx[~sfMPTokenMetadata])
365 if (metadata->empty())
367 sle->makeFieldAbsent(sfMPTokenMetadata);
371 sle->setFieldVL(sfMPTokenMetadata, *metadata);
379 sle->getType() == ltMPTOKEN_ISSUANCE,
380 "MPTokenIssuanceSet::doApply : modifying MPTokenIssuance");
382 if (*domainID != beast::kZero)
384 sle->setFieldH256(sfDomainID, *domainID);
388 if (sle->isFieldPresent(sfDomainID))
389 sle->makeFieldAbsent(sfDomainID);
393 if (
auto const pubKey =
ctx_.tx[~sfIssuerEncryptionKey])
397 sle->getType() == ltMPTOKEN_ISSUANCE,
398 "MPTokenIssuanceSet::doApply : modifying MPTokenIssuance");
400 sle->setFieldVL(sfIssuerEncryptionKey, *pubKey);
403 if (
auto const pubKey =
ctx_.tx[~sfAuditorEncryptionKey])
407 sle->getType() == ltMPTOKEN_ISSUANCE,
408 "MPTokenIssuanceSet::doApply : modifying MPTokenIssuance");
410 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)
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 mptokenIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
static constexpr std::array< MPTMutabilityFlags, 6 > kMptMutabilityFlags
constexpr FlagValue tmfMPTSetCanLock
constexpr FlagValue tmfMPTSetCanClawback
constexpr FlagValue tmfMPTSetCanHoldConfidentialBalance
bool isValidCompressedECPoint(Slice const &buffer)
Verifies that a buffer contains a valid, parsable compressed EC point.
constexpr FlagValue tmfMPTSetCanTrade
constexpr FlagValue tmfMPTSetCanTransfer
constexpr FlagValue tmfMPTSetCanEscrow
TERSubset< CanCvtToNotTEC > NotTEC
constexpr std::size_t kMaxMpTokenMetadataLength
The maximum length of MPTokenMetadata.
constexpr FlagValue tmfMPTokenIssuanceSetMutableMask
constexpr std::uint16_t kMaxTransferFee
The maximum token transfer fee allowed.
TERSubset< CanCvtToTER > TER
constexpr FlagValue tfUniversalMask
constexpr FlagValue tmfMPTSetRequireAuth
std::uint32_t canEnableFlag
State information when determining if a tx is likely to claim a fee.
State information when preflighting a tx.