rippled
Loading...
Searching...
No Matches
DelegateSet.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/DelegateSet.h>
21
22#include <xrpl/basics/Log.h>
23#include <xrpl/ledger/View.h>
24#include <xrpl/protocol/Feature.h>
25#include <xrpl/protocol/Indexes.h>
26#include <xrpl/protocol/st.h>
27
28namespace ripple {
29
32{
33 if (!ctx.rules.enabled(featurePermissionDelegation))
34 return temDISABLED;
35
36 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
37 return ret;
38
39 auto const& permissions = ctx.tx.getFieldArray(sfPermissions);
40 if (permissions.size() > permissionMaxSize)
41 return temARRAY_TOO_LARGE;
42
43 // can not authorize self
44 if (ctx.tx[sfAccount] == ctx.tx[sfAuthorize])
45 return temMALFORMED;
46
48
49 for (auto const& permission : permissions)
50 {
51 if (!permissionSet.insert(permission[sfPermissionValue]).second)
52 return temMALFORMED;
53
54 if (ctx.rules.enabled(fixDelegateV1_1) &&
56 permission[sfPermissionValue], ctx.rules))
57 return temMALFORMED;
58 }
59
60 return preflight2(ctx);
61}
62
63TER
65{
66 if (!ctx.view.exists(keylet::account(ctx.tx[sfAccount])))
67 return terNO_ACCOUNT; // LCOV_EXCL_LINE
68
69 if (!ctx.view.exists(keylet::account(ctx.tx[sfAuthorize])))
70 return tecNO_TARGET;
71
72 auto const& permissions = ctx.tx.getFieldArray(sfPermissions);
73 for (auto const& permission : permissions)
74 {
75 if (!ctx.view.rules().enabled(fixDelegateV1_1) &&
77 permission[sfPermissionValue], ctx.view.rules()))
78 {
79 // Before fixDelegateV1_1:
80 // - The check was performed during preclaim.
81 // - Transactions from amendments not yet enabled could still be
82 // delegated.
83 //
84 // After fixDelegateV1_1:
85 // - The check is performed during preflight.
86 // - Transactions from amendments not yet enabled can no longer be
87 // delegated.
88 return tecNO_PERMISSION;
89 }
90 }
91
92 return tesSUCCESS;
93}
94
95TER
97{
98 auto const sleOwner = ctx_.view().peek(keylet::account(account_));
99 if (!sleOwner)
100 return tefINTERNAL; // LCOV_EXCL_LINE
101
102 auto const& authAccount = ctx_.tx[sfAuthorize];
103 auto const delegateKey = keylet::delegate(account_, authAccount);
104
105 auto sle = ctx_.view().peek(delegateKey);
106 if (sle)
107 {
108 auto const& permissions = ctx_.tx.getFieldArray(sfPermissions);
109 if (permissions.empty())
110 // if permissions array is empty, delete the ledger object.
111 return deleteDelegate(view(), sle, account_, j_);
112
113 sle->setFieldArray(sfPermissions, permissions);
114 ctx_.view().update(sle);
115 return tesSUCCESS;
116 }
117
118 STAmount const reserve{ctx_.view().fees().accountReserve(
119 sleOwner->getFieldU32(sfOwnerCount) + 1)};
120
121 if (mPriorBalance < reserve)
123
124 auto const& permissions = ctx_.tx.getFieldArray(sfPermissions);
125 if (!permissions.empty())
126 {
127 sle = std::make_shared<SLE>(delegateKey);
128 sle->setAccountID(sfAccount, account_);
129 sle->setAccountID(sfAuthorize, authAccount);
130
131 sle->setFieldArray(sfPermissions, permissions);
132 auto const page = ctx_.view().dirInsert(
134 delegateKey,
136
137 if (!page)
138 return tecDIR_FULL; // LCOV_EXCL_LINE
139
140 (*sle)[sfOwnerNode] = *page;
141 ctx_.view().insert(sle);
142 adjustOwnerCount(ctx_.view(), sleOwner, 1, ctx_.journal);
143 }
144
145 return tesSUCCESS;
146}
147
148TER
150 ApplyView& view,
151 std::shared_ptr<SLE> const& sle,
152 AccountID const& account,
154{
155 if (!sle)
156 return tecINTERNAL; // LCOV_EXCL_LINE
157
158 if (!view.dirRemove(
159 keylet::ownerDir(account), (*sle)[sfOwnerNode], sle->key(), false))
160 {
161 // LCOV_EXCL_START
162 JLOG(j.fatal()) << "Unable to delete Delegate from owner.";
163 return tefBAD_LEDGER;
164 // LCOV_EXCL_STOP
165 }
166
167 auto const sleOwner = view.peek(keylet::account(account));
168 if (!sleOwner)
169 return tecINTERNAL; // LCOV_EXCL_LINE
170
171 adjustOwnerCount(view, sleOwner, -1, j);
172
173 view.erase(sle);
174
175 return tesSUCCESS;
176}
177
178} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:60
Stream fatal() const
Definition Journal.h:352
ApplyView & view()
beast::Journal const journal
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:143
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
bool dirRemove(Keylet const &directory, std::uint64_t page, uint256 const &key, bool keepRoot)
Remove an entry from a directory.
virtual void insert(std::shared_ptr< SLE > const &sle)=0
Insert a new state SLE.
std::optional< std::uint64_t > dirInsert(Keylet const &directory, uint256 const &key, std::function< void(std::shared_ptr< SLE > const &)> const &describe)
Insert an entry to a directory.
Definition ApplyView.h:317
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual void erase(std::shared_ptr< SLE > const &sle)=0
Remove a peeked SLE.
static TER preclaim(PreclaimContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
static TER deleteDelegate(ApplyView &view, std::shared_ptr< SLE > const &sle, AccountID const &account, beast::Journal j)
TER doApply() override
static Permission const & getInstance()
bool isDelegatable(std::uint32_t const &permissionValue, Rules const &rules) const
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:130
STArray const & getFieldArray(SField const &field) const
Definition STObject.cpp:686
AccountID const account_
Definition Transactor.h:145
ApplyView & view()
Definition Transactor.h:161
beast::Journal const j_
Definition Transactor.h:143
XRPAmount mPriorBalance
Definition Transactor.h:146
ApplyContext & ctx_
Definition Transactor.h:141
T insert(T... args)
T is_same_v
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Definition Indexes.cpp:465
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:184
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:374
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::size_t constexpr permissionMaxSize
The maximum number of delegate permissions an account can grant.
Definition Protocol.h:176
void adjustOwnerCount(ApplyView &view, std::shared_ptr< SLE > const &sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
Definition View.cpp:1029
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition View.cpp:1047
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
@ tefBAD_LEDGER
Definition TER.h:170
@ tefINTERNAL
Definition TER.h:173
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
@ tecNO_TARGET
Definition TER.h:304
@ tecDIR_FULL
Definition TER.h:287
@ tecINTERNAL
Definition TER.h:310
@ tecNO_PERMISSION
Definition TER.h:305
@ tecINSUFFICIENT_RESERVE
Definition TER.h:307
@ tesSUCCESS
Definition TER.h:244
bool isTesSuccess(TER x) noexcept
Definition TER.h:674
@ terNO_ACCOUNT
Definition TER.h:217
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:605
@ temMALFORMED
Definition TER.h:87
@ temARRAY_TOO_LARGE
Definition TER.h:141
@ temDISABLED
Definition TER.h:114
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:80
ReadView const & view
Definition Transactor.h:83
State information when preflighting a tx.
Definition Transactor.h:35