rippled
Loading...
Searching...
No Matches
VaultSet.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2025 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/app/tx/detail/VaultSet.h>
21#include <xrpld/ledger/View.h>
22
23#include <xrpl/protocol/Asset.h>
24#include <xrpl/protocol/Feature.h>
25#include <xrpl/protocol/Indexes.h>
26#include <xrpl/protocol/SField.h>
27#include <xrpl/protocol/STNumber.h>
28#include <xrpl/protocol/TER.h>
29#include <xrpl/protocol/TxFlags.h>
30
31namespace ripple {
32
35{
36 if (!ctx.rules.enabled(featureSingleAssetVault))
37 return temDISABLED;
38
39 if (ctx.tx.isFieldPresent(sfDomainID) &&
40 !ctx.rules.enabled(featurePermissionedDomains))
41 return temDISABLED;
42
43 if (auto const ter = preflight1(ctx))
44 return ter;
45
46 if (ctx.tx[sfVaultID] == beast::zero)
47 {
48 JLOG(ctx.j.debug()) << "VaultSet: zero/empty vault ID.";
49 return temMALFORMED;
50 }
51
52 if (ctx.tx.getFlags() & tfUniversalMask)
53 return temINVALID_FLAG;
54
55 if (auto const data = ctx.tx[~sfData])
56 {
57 if (data->empty() || data->length() > maxDataPayloadLength)
58 {
59 JLOG(ctx.j.debug()) << "VaultSet: invalid data payload size.";
60 return temMALFORMED;
61 }
62 }
63
64 if (auto const assetMax = ctx.tx[~sfAssetsMaximum])
65 {
66 if (*assetMax < beast::zero)
67 {
68 JLOG(ctx.j.debug()) << "VaultSet: invalid max assets.";
69 return temMALFORMED;
70 }
71 }
72
73 if (!ctx.tx.isFieldPresent(sfDomainID) &&
74 !ctx.tx.isFieldPresent(sfAssetsMaximum) &&
75 !ctx.tx.isFieldPresent(sfData))
76 {
77 JLOG(ctx.j.debug()) << "VaultSet: nothing is being updated.";
78 return temMALFORMED;
79 }
80
81 return preflight2(ctx);
82}
83
84TER
86{
87 auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
88 if (!vault)
89 return tecNO_ENTRY;
90
91 // Assert that submitter is the Owner.
92 if (ctx.tx[sfAccount] != vault->at(sfOwner))
93 {
94 JLOG(ctx.j.debug()) << "VaultSet: account is not an owner.";
95 return tecNO_PERMISSION;
96 }
97
98 auto const mptIssuanceID = (*vault)[sfShareMPTID];
99 auto const sleIssuance = ctx.view.read(keylet::mptIssuance(mptIssuanceID));
100 if (!sleIssuance)
101 {
102 // LCOV_EXCL_START
103 JLOG(ctx.j.error()) << "VaultSet: missing issuance of vault shares.";
104 return tefINTERNAL;
105 // LCOV_EXCL_STOP
106 }
107
108 if (auto const domain = ctx.tx[~sfDomainID])
109 {
110 // We can only set domain if private flag was originally set
111 if ((vault->getFlags() & tfVaultPrivate) == 0)
112 {
113 JLOG(ctx.j.debug()) << "VaultSet: vault is not private";
114 return tecNO_PERMISSION;
115 }
116
117 if (*domain != beast::zero)
118 {
119 auto const sleDomain =
121 if (!sleDomain)
122 return tecOBJECT_NOT_FOUND;
123 }
124
125 // Sanity check only, this should be enforced by VaultCreate
126 if ((sleIssuance->getFlags() & lsfMPTRequireAuth) == 0)
127 {
128 // LCOV_EXCL_START
129 JLOG(ctx.j.error())
130 << "VaultSet: issuance of vault shares is not private.";
131 return tefINTERNAL;
132 // LCOV_EXCL_STOP
133 }
134 }
135
136 return tesSUCCESS;
137}
138
139TER
141{
142 // All return codes in `doApply` must be `tec`, `ter`, or `tes`.
143 // As we move checks into `preflight` and `preclaim`,
144 // we can consider downgrading them to `tef` or `tem`.
145
146 auto const& tx = ctx_.tx;
147
148 // Update existing object.
149 auto vault = view().peek(keylet::vault(tx[sfVaultID]));
150 if (!vault)
151 return tefINTERNAL; // LCOV_EXCL_LINE
152
153 auto const mptIssuanceID = (*vault)[sfShareMPTID];
154 auto const sleIssuance = view().peek(keylet::mptIssuance(mptIssuanceID));
155 if (!sleIssuance)
156 {
157 // LCOV_EXCL_START
158 JLOG(j_.error()) << "VaultSet: missing issuance of vault shares.";
159 return tefINTERNAL;
160 // LCOV_EXCL_STOP
161 }
162
163 // Update mutable flags and fields if given.
164 if (tx.isFieldPresent(sfData))
165 vault->at(sfData) = tx[sfData];
166 if (tx.isFieldPresent(sfAssetsMaximum))
167 {
168 if (tx[sfAssetsMaximum] != 0 &&
169 tx[sfAssetsMaximum] < *vault->at(sfAssetsTotal))
170 return tecLIMIT_EXCEEDED;
171 vault->at(sfAssetsMaximum) = tx[sfAssetsMaximum];
172 }
173
174 if (auto const domainId = tx[~sfDomainID]; domainId)
175 {
176 if (*domainId != beast::zero)
177 {
178 // In VaultSet::preclaim we enforce that tfVaultPrivate must have
179 // been set in the vault. We currently do not support making such a
180 // vault public (i.e. removal of tfVaultPrivate flag). The
181 // sfDomainID flag must be set in the MPTokenIssuance object and can
182 // be freely updated.
183 sleIssuance->setFieldH256(sfDomainID, *domainId);
184 }
185 else if (sleIssuance->isFieldPresent(sfDomainID))
186 {
187 sleIssuance->makeFieldAbsent(sfDomainID);
188 }
189 view().update(sleIssuance);
190 }
191
192 view().update(vault);
193
194 return tesSUCCESS;
195}
196
197} // namespace ripple
Stream error() const
Definition: Journal.h:346
Stream debug() const
Definition: Journal.h:328
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:130
bool isFieldPresent(SField const &field) const
Definition: STObject.cpp:484
std::uint32_t getFlags() const
Definition: STObject.cpp:537
ApplyView & view()
Definition: Transactor.h:159
beast::Journal const j_
Definition: Transactor.h:141
ApplyContext & ctx_
Definition: Transactor.h:140
static TER preclaim(PreclaimContext const &ctx)
Definition: VaultSet.cpp:85
TER doApply() override
Definition: VaultSet.cpp:140
static NotTEC preflight(PreflightContext const &ctx)
Definition: VaultSet.cpp:34
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Definition: Indexes.cpp:570
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition: Indexes.cpp:526
Keylet vault(AccountID const &owner, 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:25
@ lsfMPTRequireAuth
constexpr std::uint32_t const tfVaultPrivate
Definition: TxFlags.h:234
std::size_t constexpr maxDataPayloadLength
The maximum length of Data payload.
Definition: Protocol.h:120
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
Definition: Transactor.cpp:91
@ tefINTERNAL
Definition: TER.h:173
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
Definition: Transactor.cpp:160
@ tecNO_ENTRY
Definition: TER.h:306
@ tecLIMIT_EXCEEDED
Definition: TER.h:361
@ tecOBJECT_NOT_FOUND
Definition: TER.h:326
@ tecNO_PERMISSION
Definition: TER.h:305
@ tesSUCCESS
Definition: TER.h:244
constexpr std::uint32_t tfUniversalMask
Definition: TxFlags.h:63
TERSubset< CanCvtToNotTEC > NotTEC
Definition: TER.h:605
@ temMALFORMED
Definition: TER.h:87
@ temINVALID_FLAG
Definition: TER.h:111
@ temDISABLED
Definition: TER.h:114
State information when determining if a tx is likely to claim a fee.
Definition: Transactor.h:79
ReadView const & view
Definition: Transactor.h:82
beast::Journal const j
Definition: Transactor.h:87
State information when preflighting a tx.
Definition: Transactor.h:34
beast::Journal const j
Definition: Transactor.h:41