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 auto const& permissions = ctx.tx.getFieldArray(sfPermissions);
34 if (permissions.size() > permissionMaxSize)
35 return temARRAY_TOO_LARGE;
36
37 // can not authorize self
38 if (ctx.tx[sfAccount] == ctx.tx[sfAuthorize])
39 return temMALFORMED;
40
42
43 for (auto const& permission : permissions)
44 {
45 if (!permissionSet.insert(permission[sfPermissionValue]).second)
46 return temMALFORMED;
47
48 if (ctx.rules.enabled(fixDelegateV1_1) &&
50 permission[sfPermissionValue], ctx.rules))
51 return temMALFORMED;
52 }
53
54 return tesSUCCESS;
55}
56
57TER
59{
60 if (!ctx.view.exists(keylet::account(ctx.tx[sfAccount])))
61 return terNO_ACCOUNT; // LCOV_EXCL_LINE
62
63 if (!ctx.view.exists(keylet::account(ctx.tx[sfAuthorize])))
64 return tecNO_TARGET;
65
66 auto const& permissions = ctx.tx.getFieldArray(sfPermissions);
67 for (auto const& permission : permissions)
68 {
69 if (!ctx.view.rules().enabled(fixDelegateV1_1) &&
71 permission[sfPermissionValue], ctx.view.rules()))
72 {
73 // Before fixDelegateV1_1:
74 // - The check was performed during preclaim.
75 // - Transactions from amendments not yet enabled could still be
76 // delegated.
77 //
78 // After fixDelegateV1_1:
79 // - The check is performed during preflight.
80 // - Transactions from amendments not yet enabled can no longer be
81 // delegated.
82 return tecNO_PERMISSION;
83 }
84 }
85
86 return tesSUCCESS;
87}
88
89TER
91{
92 auto const sleOwner = ctx_.view().peek(keylet::account(account_));
93 if (!sleOwner)
94 return tefINTERNAL; // LCOV_EXCL_LINE
95
96 auto const& authAccount = ctx_.tx[sfAuthorize];
97 auto const delegateKey = keylet::delegate(account_, authAccount);
98
99 auto sle = ctx_.view().peek(delegateKey);
100 if (sle)
101 {
102 auto const& permissions = ctx_.tx.getFieldArray(sfPermissions);
103 if (permissions.empty())
104 // if permissions array is empty, delete the ledger object.
105 return deleteDelegate(view(), sle, account_, j_);
106
107 sle->setFieldArray(sfPermissions, permissions);
108 ctx_.view().update(sle);
109 return tesSUCCESS;
110 }
111
112 STAmount const reserve{ctx_.view().fees().accountReserve(
113 sleOwner->getFieldU32(sfOwnerCount) + 1)};
114
115 if (mPriorBalance < reserve)
117
118 auto const& permissions = ctx_.tx.getFieldArray(sfPermissions);
119 if (!permissions.empty())
120 {
121 sle = std::make_shared<SLE>(delegateKey);
122 sle->setAccountID(sfAccount, account_);
123 sle->setAccountID(sfAuthorize, authAccount);
124
125 sle->setFieldArray(sfPermissions, permissions);
126 auto const page = ctx_.view().dirInsert(
128 delegateKey,
130
131 if (!page)
132 return tecDIR_FULL; // LCOV_EXCL_LINE
133
134 (*sle)[sfOwnerNode] = *page;
135 ctx_.view().insert(sle);
136 adjustOwnerCount(ctx_.view(), sleOwner, 1, ctx_.journal);
137 }
138
139 return tesSUCCESS;
140}
141
142TER
144 ApplyView& view,
145 std::shared_ptr<SLE> const& sle,
146 AccountID const& account,
148{
149 if (!sle)
150 return tecINTERNAL; // LCOV_EXCL_LINE
151
152 if (!view.dirRemove(
153 keylet::ownerDir(account), (*sle)[sfOwnerNode], sle->key(), false))
154 {
155 // LCOV_EXCL_START
156 JLOG(j.fatal()) << "Unable to delete Delegate from owner.";
157 return tefBAD_LEDGER;
158 // LCOV_EXCL_STOP
159 }
160
161 auto const sleOwner = view.peek(keylet::account(account));
162 if (!sleOwner)
163 return tecINTERNAL; // LCOV_EXCL_LINE
164
165 adjustOwnerCount(view, sleOwner, -1, j);
166
167 view.erase(sle);
168
169 return tesSUCCESS;
170}
171
172} // 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:319
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:692
AccountID const account_
Definition Transactor.h:147
ApplyView & view()
Definition Transactor.h:163
beast::Journal const j_
Definition Transactor.h:145
XRPAmount mPriorBalance
Definition Transactor.h:148
ApplyContext & ctx_
Definition Transactor.h:143
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:1032
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition View.cpp:1050
@ tefBAD_LEDGER
Definition TER.h:170
@ tefINTERNAL
Definition TER.h:173
@ 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
@ 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
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