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