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) && !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) && !ctx.tx.isFieldPresent(sfAssetsMaximum) && !ctx.tx.isFieldPresent(sfData))
52 {
53 JLOG(ctx.j.debug()) << "VaultSet: nothing is being updated.";
54 return temMALFORMED;
55 }
56
57 return tesSUCCESS;
58}
59
60TER
62{
63 auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
64 if (!vault)
65 return tecNO_ENTRY;
66
67 // Assert that submitter is the Owner.
68 if (ctx.tx[sfAccount] != vault->at(sfOwner))
69 {
70 JLOG(ctx.j.debug()) << "VaultSet: account is not an owner.";
71 return tecNO_PERMISSION;
72 }
73
74 auto const mptIssuanceID = (*vault)[sfShareMPTID];
75 auto const sleIssuance = ctx.view.read(keylet::mptIssuance(mptIssuanceID));
76 if (!sleIssuance)
77 {
78 // LCOV_EXCL_START
79 JLOG(ctx.j.error()) << "VaultSet: missing issuance of vault shares.";
80 return tefINTERNAL;
81 // LCOV_EXCL_STOP
82 }
83
84 if (auto const domain = ctx.tx[~sfDomainID])
85 {
86 // We can only set domain if private flag was originally set
87 if (!vault->isFlag(lsfVaultPrivate))
88 {
89 JLOG(ctx.j.debug()) << "VaultSet: vault is not private";
90 return tecNO_PERMISSION;
91 }
92
93 if (*domain != beast::zero)
94 {
95 auto const sleDomain = ctx.view.read(keylet::permissionedDomain(*domain));
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()) << "VaultSet: issuance of vault shares is not private.";
105 return tefINTERNAL;
106 // LCOV_EXCL_STOP
107 }
108 }
109
110 return tesSUCCESS;
111}
112
113TER
115{
116 // All return codes in `doApply` must be `tec`, `ter`, or `tes`.
117 // As we move checks into `preflight` and `preclaim`,
118 // we can consider downgrading them to `tef` or `tem`.
119
120 auto const& tx = ctx_.tx;
121
122 // Update existing object.
123 auto vault = view().peek(keylet::vault(tx[sfVaultID]));
124 if (!vault)
125 return tefINTERNAL; // LCOV_EXCL_LINE
126
127 auto const vaultAsset = vault->at(sfAsset);
128
129 auto const mptIssuanceID = (*vault)[sfShareMPTID];
130 auto const sleIssuance = view().peek(keylet::mptIssuance(mptIssuanceID));
131 if (!sleIssuance)
132 {
133 // LCOV_EXCL_START
134 JLOG(j_.error()) << "VaultSet: missing issuance of vault shares.";
135 return tefINTERNAL;
136 // LCOV_EXCL_STOP
137 }
138
139 // Update mutable flags and fields if given.
140 if (tx.isFieldPresent(sfData))
141 vault->at(sfData) = tx[sfData];
142 if (tx.isFieldPresent(sfAssetsMaximum))
143 {
144 if (tx[sfAssetsMaximum] != 0 && 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 associateAsset(*vault, vaultAsset);
173
174 return tesSUCCESS;
175}
176
177} // namespace xrpl
Stream error() const
Definition Journal.h:319
Stream debug() const
Definition Journal.h:301
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:118
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:439
beast::Journal const j_
Definition Transactor.h:111
ApplyView & view()
Definition Transactor.h:129
ApplyContext & ctx_
Definition Transactor.h:109
static bool checkExtraFeatures(PreflightContext const &ctx)
Definition VaultSet.cpp:16
static TER preclaim(PreclaimContext const &ctx)
Definition VaultSet.cpp:61
TER doApply() override
Definition VaultSet.cpp:114
static NotTEC preflight(PreflightContext const &ctx)
Definition VaultSet.cpp:25
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:462
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:492
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Definition Indexes.cpp:510
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
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:54
ReadView const & view
Definition Transactor.h:57
beast::Journal const j
Definition Transactor.h:62
State information when preflighting a tx.
Definition Transactor.h:16
beast::Journal const j
Definition Transactor.h:23