rippled
Loading...
Searching...
No Matches
MPTokenIssuanceSet.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2024 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/app/misc/DelegateUtils.h>
21#include <xrpld/app/tx/detail/MPTokenIssuanceSet.h>
22
23#include <xrpl/protocol/Feature.h>
24#include <xrpl/protocol/LedgerFormats.h>
25#include <xrpl/protocol/TxFlags.h>
26
27namespace ripple {
28
31{
32 if (!ctx.rules.enabled(featureMPTokensV1))
33 return temDISABLED;
34
35 if (ctx.tx.isFieldPresent(sfDomainID) &&
36 !(ctx.rules.enabled(featurePermissionedDomains) &&
37 ctx.rules.enabled(featureSingleAssetVault)))
38 return temDISABLED;
39
40 if (ctx.tx.isFieldPresent(sfDomainID) && ctx.tx.isFieldPresent(sfHolder))
41 return temMALFORMED;
42
43 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
44 return ret;
45
46 auto const txFlags = ctx.tx.getFlags();
47
48 // check flags
49 if (txFlags & tfMPTokenIssuanceSetMask)
50 return temINVALID_FLAG;
51 // fails if both flags are set
52 else if ((txFlags & tfMPTLock) && (txFlags & tfMPTUnlock))
53 return temINVALID_FLAG;
54
55 auto const accountID = ctx.tx[sfAccount];
56 auto const holderID = ctx.tx[~sfHolder];
57 if (holderID && accountID == holderID)
58 return temMALFORMED;
59
60 if (ctx.rules.enabled(featureSingleAssetVault))
61 {
62 // Is this transaction actually changing anything ?
63 if (txFlags == 0 && !ctx.tx.isFieldPresent(sfDomainID))
64 return temMALFORMED;
65 }
66
67 return preflight2(ctx);
68}
69
70TER
72{
73 auto const delegate = tx[~sfDelegate];
74 if (!delegate)
75 return tesSUCCESS;
76
77 auto const delegateKey = keylet::delegate(tx[sfAccount], *delegate);
78 auto const sle = view.read(delegateKey);
79
80 if (!sle)
82
83 if (checkTxPermission(sle, tx) == tesSUCCESS)
84 return tesSUCCESS;
85
86 auto const txFlags = tx.getFlags();
87
88 // this is added in case more flags will be added for MPTokenIssuanceSet
89 // in the future. Currently unreachable.
91 return tecNO_DELEGATE_PERMISSION; // LCOV_EXCL_LINE
92
94 loadGranularPermission(sle, ttMPTOKEN_ISSUANCE_SET, granularPermissions);
95
96 if (txFlags & tfMPTLock &&
97 !granularPermissions.contains(MPTokenIssuanceLock))
99
100 if (txFlags & tfMPTUnlock &&
101 !granularPermissions.contains(MPTokenIssuanceUnlock))
103
104 return tesSUCCESS;
105}
106
107TER
109{
110 // ensure that issuance exists
111 auto const sleMptIssuance =
112 ctx.view.read(keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID]));
113 if (!sleMptIssuance)
114 return tecOBJECT_NOT_FOUND;
115
116 if (!sleMptIssuance->isFlag(lsfMPTCanLock))
117 {
118 // For readability two separate `if` rather than `||` of two conditions
119 if (!ctx.view.rules().enabled(featureSingleAssetVault))
120 return tecNO_PERMISSION;
121 else if (ctx.tx.isFlag(tfMPTLock) || ctx.tx.isFlag(tfMPTUnlock))
122 return tecNO_PERMISSION;
123 }
124
125 // ensure it is issued by the tx submitter
126 if ((*sleMptIssuance)[sfIssuer] != ctx.tx[sfAccount])
127 return tecNO_PERMISSION;
128
129 if (auto const holderID = ctx.tx[~sfHolder])
130 {
131 // make sure holder account exists
132 if (!ctx.view.exists(keylet::account(*holderID)))
133 return tecNO_DST;
134
135 // the mptoken must exist
136 if (!ctx.view.exists(
137 keylet::mptoken(ctx.tx[sfMPTokenIssuanceID], *holderID)))
138 return tecOBJECT_NOT_FOUND;
139 }
140
141 if (auto const domain = ctx.tx[~sfDomainID])
142 {
143 if (not sleMptIssuance->isFlag(lsfMPTRequireAuth))
144 return tecNO_PERMISSION;
145
146 if (*domain != beast::zero)
147 {
148 auto const sleDomain =
150 if (!sleDomain)
151 return tecOBJECT_NOT_FOUND;
152 }
153 }
154
155 return tesSUCCESS;
156}
157
158TER
160{
161 auto const mptIssuanceID = ctx_.tx[sfMPTokenIssuanceID];
162 auto const txFlags = ctx_.tx.getFlags();
163 auto const holderID = ctx_.tx[~sfHolder];
164 auto const domainID = ctx_.tx[~sfDomainID];
166
167 if (holderID)
168 sle = view().peek(keylet::mptoken(mptIssuanceID, *holderID));
169 else
170 sle = view().peek(keylet::mptIssuance(mptIssuanceID));
171
172 if (!sle)
173 return tecINTERNAL;
174
175 std::uint32_t const flagsIn = sle->getFieldU32(sfFlags);
176 std::uint32_t flagsOut = flagsIn;
177
178 if (txFlags & tfMPTLock)
179 flagsOut |= lsfMPTLocked;
180 else if (txFlags & tfMPTUnlock)
181 flagsOut &= ~lsfMPTLocked;
182
183 if (flagsIn != flagsOut)
184 sle->setFieldU32(sfFlags, flagsOut);
185
186 if (domainID)
187 {
188 // This is enforced in preflight.
189 XRPL_ASSERT(
190 sle->getType() == ltMPTOKEN_ISSUANCE,
191 "MPTokenIssuanceSet::doApply : modifying MPTokenIssuance");
192
193 if (*domainID != beast::zero)
194 {
195 sle->setFieldH256(sfDomainID, *domainID);
196 }
197 else
198 {
199 if (sle->isFieldPresent(sfDomainID))
200 sle->makeFieldAbsent(sfDomainID);
201 }
202 }
203
204 view().update(sle);
205
206 return tesSUCCESS;
207}
208
209} // namespace ripple
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
static TER preclaim(PreclaimContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
static TER checkPermission(ReadView const &view, STTx const &tx)
A view into a ledger.
Definition ReadView.h:52
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:130
bool isFlag(std::uint32_t) const
Definition STObject.cpp:531
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:484
std::uint32_t getFlags() const
Definition STObject.cpp:537
ApplyView & view()
Definition Transactor.h:159
ApplyContext & ctx_
Definition Transactor.h:140
T contains(T... args)
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Definition Indexes.cpp:540
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Definition Indexes.cpp:465
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Definition Indexes.cpp:570
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:526
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:184
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
constexpr std::uint32_t const tfMPTokenIssuanceSetMask
Definition TxFlags.h:161
constexpr std::uint32_t const tfMPTokenIssuanceSetPermissionMask
Definition TxFlags.h:162
constexpr std::uint32_t const tfMPTUnlock
Definition TxFlags.h:160
@ lsfMPTRequireAuth
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
void loadGranularPermission(std::shared_ptr< SLE const > const &delegate, TxType const &type, std::unordered_set< GranularPermissionType > &granularPermissions)
Load the granular permissions granted to the delegate account for the specified transaction type.
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
TER checkTxPermission(std::shared_ptr< SLE const > const &delegate, STTx const &tx)
Check if the delegate account has permission to execute the transaction.
@ tecNO_DELEGATE_PERMISSION
Definition TER.h:364
@ tecNO_DST
Definition TER.h:290
@ tecOBJECT_NOT_FOUND
Definition TER.h:326
@ tecINTERNAL
Definition TER.h:310
@ tecNO_PERMISSION
Definition TER.h:305
constexpr std::uint32_t const tfMPTLock
Definition TxFlags.h:159
@ tesSUCCESS
Definition TER.h:244
bool isTesSuccess(TER x) noexcept
Definition TER.h:674
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:605
@ temMALFORMED
Definition TER.h:87
@ temINVALID_FLAG
Definition TER.h:111
@ temDISABLED
Definition TER.h:114
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:79
ReadView const & view
Definition Transactor.h:82
State information when preflighting a tx.
Definition Transactor.h:34