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