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
22#include <xrpl/ledger/View.h>
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->isFlag(lsfVaultPrivate))
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 lsfVaultPrivate must have
179 // been set in the vault. We currently do not support making such a
180 // vault public (i.e. removal of lsfVaultPrivate 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
@ lsfVaultPrivate
@ lsfMPTRequireAuth
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.
@ tefINTERNAL
Definition TER.h:173
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
@ 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