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/TER.h>
10#include <xrpl/protocol/TxFlags.h>
11
12namespace xrpl {
13
14bool
16{
17 if (ctx.tx.isFieldPresent(sfDomainID) &&
18 !ctx.rules.enabled(featurePermissionedDomains))
19 return false;
20
21 return true;
22}
23
26{
27 if (ctx.tx[sfVaultID] == beast::zero)
28 {
29 JLOG(ctx.j.debug()) << "VaultSet: zero/empty vault ID.";
30 return temMALFORMED;
31 }
32
33 if (auto const data = ctx.tx[~sfData])
34 {
35 if (data->empty() || data->length() > maxDataPayloadLength)
36 {
37 JLOG(ctx.j.debug()) << "VaultSet: invalid data payload size.";
38 return temMALFORMED;
39 }
40 }
41
42 if (auto const assetMax = ctx.tx[~sfAssetsMaximum])
43 {
44 if (*assetMax < beast::zero)
45 {
46 JLOG(ctx.j.debug()) << "VaultSet: invalid max assets.";
47 return temMALFORMED;
48 }
49 }
50
51 if (!ctx.tx.isFieldPresent(sfDomainID) &&
52 !ctx.tx.isFieldPresent(sfAssetsMaximum) &&
53 !ctx.tx.isFieldPresent(sfData))
54 {
55 JLOG(ctx.j.debug()) << "VaultSet: nothing is being updated.";
56 return temMALFORMED;
57 }
58
59 return tesSUCCESS;
60}
61
62TER
64{
65 auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
66 if (!vault)
67 return tecNO_ENTRY;
68
69 // Assert that submitter is the Owner.
70 if (ctx.tx[sfAccount] != vault->at(sfOwner))
71 {
72 JLOG(ctx.j.debug()) << "VaultSet: account is not an owner.";
73 return tecNO_PERMISSION;
74 }
75
76 auto const mptIssuanceID = (*vault)[sfShareMPTID];
77 auto const sleIssuance = ctx.view.read(keylet::mptIssuance(mptIssuanceID));
78 if (!sleIssuance)
79 {
80 // LCOV_EXCL_START
81 JLOG(ctx.j.error()) << "VaultSet: missing issuance of vault shares.";
82 return tefINTERNAL;
83 // LCOV_EXCL_STOP
84 }
85
86 if (auto const domain = ctx.tx[~sfDomainID])
87 {
88 // We can only set domain if private flag was originally set
89 if (!vault->isFlag(lsfVaultPrivate))
90 {
91 JLOG(ctx.j.debug()) << "VaultSet: vault is not private";
92 return tecNO_PERMISSION;
93 }
94
95 if (*domain != beast::zero)
96 {
97 auto const sleDomain =
99 if (!sleDomain)
100 return tecOBJECT_NOT_FOUND;
101 }
102
103 // Sanity check only, this should be enforced by VaultCreate
104 if ((sleIssuance->getFlags() & lsfMPTRequireAuth) == 0)
105 {
106 // LCOV_EXCL_START
107 JLOG(ctx.j.error())
108 << "VaultSet: issuance of vault shares is not private.";
109 return tefINTERNAL;
110 // LCOV_EXCL_STOP
111 }
112 }
113
114 return tesSUCCESS;
115}
116
117TER
119{
120 // All return codes in `doApply` must be `tec`, `ter`, or `tes`.
121 // As we move checks into `preflight` and `preclaim`,
122 // we can consider downgrading them to `tef` or `tem`.
123
124 auto const& tx = ctx_.tx;
125
126 // Update existing object.
127 auto vault = view().peek(keylet::vault(tx[sfVaultID]));
128 if (!vault)
129 return tefINTERNAL; // LCOV_EXCL_LINE
130
131 auto const mptIssuanceID = (*vault)[sfShareMPTID];
132 auto const sleIssuance = view().peek(keylet::mptIssuance(mptIssuanceID));
133 if (!sleIssuance)
134 {
135 // LCOV_EXCL_START
136 JLOG(j_.error()) << "VaultSet: missing issuance of vault shares.";
137 return tefINTERNAL;
138 // LCOV_EXCL_STOP
139 }
140
141 // Update mutable flags and fields if given.
142 if (tx.isFieldPresent(sfData))
143 vault->at(sfData) = tx[sfData];
144 if (tx.isFieldPresent(sfAssetsMaximum))
145 {
146 if (tx[sfAssetsMaximum] != 0 &&
147 tx[sfAssetsMaximum] < *vault->at(sfAssetsTotal))
148 return tecLIMIT_EXCEEDED;
149 vault->at(sfAssetsMaximum) = tx[sfAssetsMaximum];
150 }
151
152 if (auto const domainId = tx[~sfDomainID]; domainId)
153 {
154 if (*domainId != beast::zero)
155 {
156 // In VaultSet::preclaim we enforce that lsfVaultPrivate must have
157 // been set in the vault. We currently do not support making such a
158 // vault public (i.e. removal of lsfVaultPrivate flag). The
159 // sfDomainID flag must be set in the MPTokenIssuance object and can
160 // be freely updated.
161 sleIssuance->setFieldH256(sfDomainID, *domainId);
162 }
163 else if (sleIssuance->isFieldPresent(sfDomainID))
164 {
165 sleIssuance->makeFieldAbsent(sfDomainID);
166 }
167 view().update(sleIssuance);
168 }
169
170 // Note, we must update Vault object even if only DomainID is being updated
171 // in Issuance object. Otherwise it's really difficult for Vault invariants
172 // to verify the operation.
173 view().update(vault);
174
175 return tesSUCCESS;
176}
177
178} // 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:111
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:15
static TER preclaim(PreclaimContext const &ctx)
Definition VaultSet.cpp:63
TER doApply() override
Definition VaultSet.cpp:118
static NotTEC preflight(PreflightContext const &ctx)
Definition VaultSet.cpp:25
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:238
@ 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
@ 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