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#include <xrpld/ledger/View.h>
22
23#include <xrpl/basics/Log.h>
24#include <xrpl/protocol/Feature.h>
25#include <xrpl/protocol/Indexes.h>
26#include <xrpl/protocol/TxFlags.h>
27#include <xrpl/protocol/st.h>
28
29namespace ripple {
30
33{
34 if (!ctx.rules.enabled(featurePermissionDelegation))
35 return temDISABLED;
36
37 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
38 return ret;
39
40 auto const& permissions = ctx.tx.getFieldArray(sfPermissions);
41 if (permissions.size() > permissionMaxSize)
42 return temARRAY_TOO_LARGE;
43
44 // can not authorize self
45 if (ctx.tx[sfAccount] == ctx.tx[sfAuthorize])
46 return temMALFORMED;
47
49
50 for (auto const& permission : permissions)
51 {
52 if (!permissionSet.insert(permission[sfPermissionValue]).second)
53 return temMALFORMED;
54 }
55
56 return preflight2(ctx);
57}
58
59TER
61{
62 if (!ctx.view.exists(keylet::account(ctx.tx[sfAccount])))
63 return terNO_ACCOUNT; // LCOV_EXCL_LINE
64
65 if (!ctx.view.exists(keylet::account(ctx.tx[sfAuthorize])))
66 return tecNO_TARGET;
67
68 auto const& permissions = ctx.tx.getFieldArray(sfPermissions);
69 for (auto const& permission : permissions)
70 {
71 auto const permissionValue = permission[sfPermissionValue];
72 if (!Permission::getInstance().isDelegatable(permissionValue))
73 return tecNO_PERMISSION;
74 }
75
76 return tesSUCCESS;
77}
78
79TER
81{
82 auto const sleOwner = ctx_.view().peek(keylet::account(account_));
83 if (!sleOwner)
84 return tefINTERNAL; // LCOV_EXCL_LINE
85
86 auto const& authAccount = ctx_.tx[sfAuthorize];
87 auto const delegateKey = keylet::delegate(account_, authAccount);
88
89 auto sle = ctx_.view().peek(delegateKey);
90 if (sle)
91 {
92 auto const& permissions = ctx_.tx.getFieldArray(sfPermissions);
93 if (permissions.empty())
94 // if permissions array is empty, delete the ledger object.
95 return deleteDelegate(view(), sle, account_, j_);
96
97 sle->setFieldArray(sfPermissions, permissions);
98 ctx_.view().update(sle);
99 return tesSUCCESS;
100 }
101
102 STAmount const reserve{ctx_.view().fees().accountReserve(
103 sleOwner->getFieldU32(sfOwnerCount) + 1)};
104
105 if (mPriorBalance < reserve)
107
108 auto const& permissions = ctx_.tx.getFieldArray(sfPermissions);
109 if (!permissions.empty())
110 {
111 sle = std::make_shared<SLE>(delegateKey);
112 sle->setAccountID(sfAccount, account_);
113 sle->setAccountID(sfAuthorize, authAccount);
114
115 sle->setFieldArray(sfPermissions, permissions);
116 auto const page = ctx_.view().dirInsert(
118 delegateKey,
120
121 if (!page)
122 return tecDIR_FULL; // LCOV_EXCL_LINE
123
124 (*sle)[sfOwnerNode] = *page;
125 ctx_.view().insert(sle);
126 adjustOwnerCount(ctx_.view(), sleOwner, 1, ctx_.journal);
127 }
128
129 return tesSUCCESS;
130}
131
132TER
134 ApplyView& view,
135 std::shared_ptr<SLE> const& sle,
136 AccountID const& account,
138{
139 if (!sle)
140 return tecINTERNAL; // LCOV_EXCL_LINE
141
142 if (!view.dirRemove(
143 keylet::ownerDir(account), (*sle)[sfOwnerNode], sle->key(), false))
144 {
145 // LCOV_EXCL_START
146 JLOG(j.fatal()) << "Unable to delete Delegate from owner.";
147 return tefBAD_LEDGER;
148 // LCOV_EXCL_STOP
149 }
150
151 auto const sleOwner = view.peek(keylet::account(account));
152 if (!sleOwner)
153 return tecINTERNAL; // LCOV_EXCL_LINE
154
155 adjustOwnerCount(view, sleOwner, -1, j);
156
157 view.erase(sle);
158
159 return tesSUCCESS;
160}
161
162} // namespace ripple
A generic endpoint for log messages.
Definition: Journal.h:60
Stream fatal() const
Definition: Journal.h:352
ApplyView & view()
Definition: ApplyContext.h:78
beast::Journal const journal
Definition: ApplyContext.h:75
Writeable view to a ledger, for applying a transaction.
Definition: ApplyView.h:144
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.
Definition: ApplyView.cpp:190
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:318
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)
Definition: DelegateSet.cpp:60
static NotTEC preflight(PreflightContext const &ctx)
Definition: DelegateSet.cpp:32
static TER deleteDelegate(ApplyView &view, std::shared_ptr< SLE > const &sle, AccountID const &account, beast::Journal j)
TER doApply() override
Definition: DelegateSet.cpp:80
static Permission const & getInstance()
Definition: Permissions.cpp:84
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.
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:143
ApplyView & view()
Definition: Transactor.h:159
beast::Journal const j_
Definition: Transactor.h:141
XRPAmount mPriorBalance
Definition: Transactor.h:144
ApplyContext & ctx_
Definition: Transactor.h:140
T insert(T... args)
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:170
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition: View.cpp:1049
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
Definition: Transactor.cpp:91
@ tefBAD_LEDGER
Definition: TER.h:170
@ tefINTERNAL
Definition: TER.h:173
static bool adjustOwnerCount(ApplyContext &ctx, int count)
Definition: SetOracle.cpp:186
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
Definition: Transactor.cpp:160
@ 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.
Definition: protocol/Fees.h:49
State information when determining if a tx is likely to claim a fee.
Definition: Transactor.h:79
ReadView const & view
Definition: Transactor.h:82
State information when preflighting a tx.
Definition: Transactor.h:34