rippled
Loading...
Searching...
No Matches
VaultSet.cpp
1#include <xrpld/app/tx/detail/VaultSet.h>
2
3#include <xrpl/ledger/View.h>
4#include <xrpl/protocol/Asset.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/Indexes.h>
7#include <xrpl/protocol/SField.h>
8#include <xrpl/protocol/STNumber.h>
9#include <xrpl/protocol/STTakesAsset.h>
10#include <xrpl/protocol/TER.h>
11#include <xrpl/protocol/TxFlags.h>
12
13namespace xrpl {
14
15bool
17{
18 if (ctx.tx.isFieldPresent(sfDomainID) &&
19 !ctx.rules.enabled(featurePermissionedDomains))
20 return false;
21
22 return true;
23}
24
27{
28 if (ctx.tx[sfVaultID] == beast::zero)
29 {
30 JLOG(ctx.j.debug()) << "VaultSet: zero/empty vault ID.";
31 return temMALFORMED;
32 }
33
34 if (auto const data = ctx.tx[~sfData])
35 {
36 if (data->empty() || data->length() > maxDataPayloadLength)
37 {
38 JLOG(ctx.j.debug()) << "VaultSet: invalid data payload size.";
39 return temMALFORMED;
40 }
41 }
42
43 if (auto const assetMax = ctx.tx[~sfAssetsMaximum])
44 {
45 if (*assetMax < beast::zero)
46 {
47 JLOG(ctx.j.debug()) << "VaultSet: invalid max assets.";
48 return temMALFORMED;
49 }
50 }
51
52 if (!ctx.tx.isFieldPresent(sfDomainID) &&
53 !ctx.tx.isFieldPresent(sfAssetsMaximum) &&
54 !ctx.tx.isFieldPresent(sfData))
55 {
56 JLOG(ctx.j.debug()) << "VaultSet: nothing is being updated.";
57 return temMALFORMED;
58 }
59
60 return tesSUCCESS;
61}
62
63TER
65{
66 auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
67 if (!vault)
68 return tecNO_ENTRY;
69
70 // Assert that submitter is the Owner.
71 if (ctx.tx[sfAccount] != vault->at(sfOwner))
72 {
73 JLOG(ctx.j.debug()) << "VaultSet: account is not an owner.";
74 return tecNO_PERMISSION;
75 }
76
77 auto const mptIssuanceID = (*vault)[sfShareMPTID];
78 auto const sleIssuance = ctx.view.read(keylet::mptIssuance(mptIssuanceID));
79 if (!sleIssuance)
80 {
81 // LCOV_EXCL_START
82 JLOG(ctx.j.error()) << "VaultSet: missing issuance of vault shares.";
83 return tefINTERNAL;
84 // LCOV_EXCL_STOP
85 }
86
87 if (auto const domain = ctx.tx[~sfDomainID])
88 {
89 // We can only set domain if private flag was originally set
90 if (!vault->isFlag(lsfVaultPrivate))
91 {
92 JLOG(ctx.j.debug()) << "VaultSet: vault is not private";
93 return tecNO_PERMISSION;
94 }
95
96 if (*domain != beast::zero)
97 {
98 auto const sleDomain =
100 if (!sleDomain)
101 return tecOBJECT_NOT_FOUND;
102 }
103
104 // Sanity check only, this should be enforced by VaultCreate
105 if ((sleIssuance->getFlags() & lsfMPTRequireAuth) == 0)
106 {
107 // LCOV_EXCL_START
108 JLOG(ctx.j.error())
109 << "VaultSet: issuance of vault shares is not private.";
110 return tefINTERNAL;
111 // LCOV_EXCL_STOP
112 }
113 }
114
115 return tesSUCCESS;
116}
117
118TER
120{
121 // All return codes in `doApply` must be `tec`, `ter`, or `tes`.
122 // As we move checks into `preflight` and `preclaim`,
123 // we can consider downgrading them to `tef` or `tem`.
124
125 auto const& tx = ctx_.tx;
126
127 // Update existing object.
128 auto vault = view().peek(keylet::vault(tx[sfVaultID]));
129 if (!vault)
130 return tefINTERNAL; // LCOV_EXCL_LINE
131
132 auto const vaultAsset = vault->at(sfAsset);
133
134 auto const mptIssuanceID = (*vault)[sfShareMPTID];
135 auto const sleIssuance = view().peek(keylet::mptIssuance(mptIssuanceID));
136 if (!sleIssuance)
137 {
138 // LCOV_EXCL_START
139 JLOG(j_.error()) << "VaultSet: missing issuance of vault shares.";
140 return tefINTERNAL;
141 // LCOV_EXCL_STOP
142 }
143
144 // Update mutable flags and fields if given.
145 if (tx.isFieldPresent(sfData))
146 vault->at(sfData) = tx[sfData];
147 if (tx.isFieldPresent(sfAssetsMaximum))
148 {
149 if (tx[sfAssetsMaximum] != 0 &&
150 tx[sfAssetsMaximum] < *vault->at(sfAssetsTotal))
151 return tecLIMIT_EXCEEDED;
152 vault->at(sfAssetsMaximum) = tx[sfAssetsMaximum];
153 }
154
155 if (auto const domainId = tx[~sfDomainID]; domainId)
156 {
157 if (*domainId != beast::zero)
158 {
159 // In VaultSet::preclaim we enforce that lsfVaultPrivate must have
160 // been set in the vault. We currently do not support making such a
161 // vault public (i.e. removal of lsfVaultPrivate flag). The
162 // sfDomainID flag must be set in the MPTokenIssuance object and can
163 // be freely updated.
164 sleIssuance->setFieldH256(sfDomainID, *domainId);
165 }
166 else if (sleIssuance->isFieldPresent(sfDomainID))
167 {
168 sleIssuance->makeFieldAbsent(sfDomainID);
169 }
170 view().update(sleIssuance);
171 }
172
173 // Note, we must update Vault object even if only DomainID is being updated
174 // in Issuance object. Otherwise it's really difficult for Vault invariants
175 // to verify the operation.
176 view().update(vault);
177
178 associateAsset(*vault, vaultAsset);
179
180 return tesSUCCESS;
181}
182
183} // namespace xrpl
Stream error() const
Definition Journal.h:327
Stream debug() const
Definition Journal.h:309
STTx const & tx
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.
virtual std::shared_ptr< SLE const > 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.
Definition Rules.cpp:123
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:465
beast::Journal const j_
Definition Transactor.h:126
ApplyView & view()
Definition Transactor.h:144
ApplyContext & ctx_
Definition Transactor.h:124
static bool checkExtraFeatures(PreflightContext const &ctx)
Definition VaultSet.cpp:16
static TER preclaim(PreclaimContext const &ctx)
Definition VaultSet.cpp:64
TER doApply() override
Definition VaultSet.cpp:119
static NotTEC preflight(PreflightContext const &ctx)
Definition VaultSet.cpp:26
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:508
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:546
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Definition Indexes.cpp:564
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
@ tefINTERNAL
Definition TER.h:154
std::size_t constexpr maxDataPayloadLength
The maximum length of Data payload.
Definition Protocol.h:239
@ temMALFORMED
Definition TER.h:68
@ tecNO_ENTRY
Definition TER.h:288
@ tecOBJECT_NOT_FOUND
Definition TER.h:308
@ tecLIMIT_EXCEEDED
Definition TER.h:343
@ tecNO_PERMISSION
Definition TER.h:287
@ lsfMPTRequireAuth
@ lsfVaultPrivate
void associateAsset(STLedgerEntry &sle, Asset const &asset)
Associate an Asset with all sMD_NeedsAsset fields in a ledger entry.
@ tesSUCCESS
Definition TER.h:226
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:61
ReadView const & view
Definition Transactor.h:64
beast::Journal const j
Definition Transactor.h:69
State information when preflighting a tx.
Definition Transactor.h:16
beast::Journal const j
Definition Transactor.h:23