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
49 permission[sfPermissionValue], ctx.rules))
50 return temMALFORMED;
51 }
52
53 return tesSUCCESS;
54}
55
56TER
58{
59 if (!ctx.view.exists(keylet::account(ctx.tx[sfAccount])))
60 return terNO_ACCOUNT; // LCOV_EXCL_LINE
61
62 if (!ctx.view.exists(keylet::account(ctx.tx[sfAuthorize])))
63 return tecNO_TARGET;
64
65 return tesSUCCESS;
66}
67
68TER
70{
71 auto const sleOwner = ctx_.view().peek(keylet::account(account_));
72 if (!sleOwner)
73 return tefINTERNAL; // LCOV_EXCL_LINE
74
75 auto const& authAccount = ctx_.tx[sfAuthorize];
76 auto const delegateKey = keylet::delegate(account_, authAccount);
77
78 auto sle = ctx_.view().peek(delegateKey);
79 if (sle)
80 {
81 auto const& permissions = ctx_.tx.getFieldArray(sfPermissions);
82 if (permissions.empty())
83 // if permissions array is empty, delete the ledger object.
84 return deleteDelegate(view(), sle, account_, j_);
85
86 sle->setFieldArray(sfPermissions, permissions);
87 ctx_.view().update(sle);
88 return tesSUCCESS;
89 }
90
91 STAmount const reserve{ctx_.view().fees().accountReserve(
92 sleOwner->getFieldU32(sfOwnerCount) + 1)};
93
94 if (mPriorBalance < reserve)
96
97 auto const& permissions = ctx_.tx.getFieldArray(sfPermissions);
98 if (!permissions.empty())
99 {
100 sle = std::make_shared<SLE>(delegateKey);
101 sle->setAccountID(sfAccount, account_);
102 sle->setAccountID(sfAuthorize, authAccount);
103
104 sle->setFieldArray(sfPermissions, permissions);
105 auto const page = ctx_.view().dirInsert(
107 delegateKey,
109
110 if (!page)
111 return tecDIR_FULL; // LCOV_EXCL_LINE
112
113 (*sle)[sfOwnerNode] = *page;
114 ctx_.view().insert(sle);
115 adjustOwnerCount(ctx_.view(), sleOwner, 1, ctx_.journal);
116 }
117
118 return tesSUCCESS;
119}
120
121TER
123 ApplyView& view,
124 std::shared_ptr<SLE> const& sle,
125 AccountID const& account,
127{
128 if (!sle)
129 return tecINTERNAL; // LCOV_EXCL_LINE
130
131 if (!view.dirRemove(
132 keylet::ownerDir(account), (*sle)[sfOwnerNode], sle->key(), false))
133 {
134 // LCOV_EXCL_START
135 JLOG(j.fatal()) << "Unable to delete Delegate from owner.";
136 return tefBAD_LEDGER;
137 // LCOV_EXCL_STOP
138 }
139
140 auto const sleOwner = view.peek(keylet::account(account));
141 if (!sleOwner)
142 return tecINTERNAL; // LCOV_EXCL_LINE
143
144 adjustOwnerCount(view, sleOwner, -1, j);
145
146 view.erase(sle);
147
148 return tesSUCCESS;
149}
150
151} // 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.
STArray const & getFieldArray(SField const &field) const
Definition STObject.cpp:702
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:179
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:305
@ tecDIR_FULL
Definition TER.h:288
@ tecINTERNAL
Definition TER.h:311
@ tecINSUFFICIENT_RESERVE
Definition TER.h:308
@ tesSUCCESS
Definition TER.h:245
@ terNO_ACCOUNT
Definition TER.h:217
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:609
@ 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