rippled
Loading...
Searching...
No Matches
PermissionedDomainSet.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2024 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/PermissionedDomainSet.h>
21
22#include <xrpl/ledger/CredentialHelpers.h>
23#include <xrpl/ledger/View.h>
24#include <xrpl/protocol/STObject.h>
25#include <xrpl/protocol/TxFlags.h>
26
27#include <optional>
28
29namespace ripple {
30
31bool
33{
34 return ctx.rules.enabled(featureCredentials);
35}
36
39{
40 if (auto err = credentials::checkArray(
41 ctx.tx.getFieldArray(sfAcceptedCredentials),
43 ctx.j);
44 !isTesSuccess(err))
45 return err;
46
47 auto const domain = ctx.tx.at(~sfDomainID);
48 if (domain && *domain == beast::zero)
49 return temMALFORMED;
50
51 return tesSUCCESS;
52}
53
54TER
56{
57 auto const account = ctx.tx.getAccountID(sfAccount);
58
59 if (!ctx.view.exists(keylet::account(account)))
60 return tefINTERNAL; // LCOV_EXCL_LINE
61
62 auto const& credentials = ctx.tx.getFieldArray(sfAcceptedCredentials);
63 for (auto const& credential : credentials)
64 {
65 if (!ctx.view.exists(
66 keylet::account(credential.getAccountID(sfIssuer))))
67 return tecNO_ISSUER;
68 }
69
70 if (ctx.tx.isFieldPresent(sfDomainID))
71 {
72 auto const sleDomain = ctx.view.read(
74 if (!sleDomain)
75 return tecNO_ENTRY;
76 if (sleDomain->getAccountID(sfOwner) != account)
77 return tecNO_PERMISSION;
78 }
79
80 return tesSUCCESS;
81}
82
84TER
86{
87 auto const ownerSle = view().peek(keylet::account(account_));
88 if (!ownerSle)
89 return tefINTERNAL; // LCOV_EXCL_LINE
90
91 auto const sortedTxCredentials =
92 credentials::makeSorted(ctx_.tx.getFieldArray(sfAcceptedCredentials));
93 STArray sortedLE(sfAcceptedCredentials, sortedTxCredentials.size());
94 for (auto const& p : sortedTxCredentials)
95 {
96 auto cred = STObject::makeInnerObject(sfCredential);
97 cred.setAccountID(sfIssuer, p.first);
98 cred.setFieldVL(sfCredentialType, p.second);
99 sortedLE.push_back(std::move(cred));
100 }
101
102 if (ctx_.tx.isFieldPresent(sfDomainID))
103 {
104 // Modify existing permissioned domain.
105 auto slePd = view().peek(
107 if (!slePd)
108 return tefINTERNAL; // LCOV_EXCL_LINE
109 slePd->peekFieldArray(sfAcceptedCredentials) = std::move(sortedLE);
110 view().update(slePd);
111 }
112 else
113 {
114 // Create new permissioned domain.
115 // Check reserve availability for new object creation
116 auto const balance = STAmount((*ownerSle)[sfBalance]).xrp();
117 auto const reserve =
118 ctx_.view().fees().accountReserve((*ownerSle)[sfOwnerCount] + 1);
119 if (balance < reserve)
121
122 Keylet const pdKeylet = keylet::permissionedDomain(
123 account_, ctx_.tx.getFieldU32(sfSequence));
124 auto slePd = std::make_shared<SLE>(pdKeylet);
125 if (!slePd)
126 return tefINTERNAL; // LCOV_EXCL_LINE
127
128 slePd->setAccountID(sfOwner, account_);
129 slePd->setFieldU32(sfSequence, ctx_.tx.getFieldU32(sfSequence));
130 slePd->peekFieldArray(sfAcceptedCredentials) = std::move(sortedLE);
131 auto const page = view().dirInsert(
133 if (!page)
134 return tecDIR_FULL; // LCOV_EXCL_LINE
135
136 slePd->setFieldU64(sfOwnerNode, *page);
137 // If we succeeded, the new entry counts against the creator's reserve.
138 adjustOwnerCount(view(), ownerSle, 1, ctx_.journal);
139 view().insert(slePd);
140 }
141
142 return tesSUCCESS;
143}
144
145} // namespace ripple
ApplyView & view()
beast::Journal const journal
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
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.
static NotTEC preflight(PreflightContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
TER doApply() override
Attempt to create the Permissioned Domain.
static bool checkExtraFeatures(PreflightContext const &ctx)
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
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
XRPAmount xrp() const
Definition STAmount.cpp:306
void push_back(STObject const &object)
Definition STArray.h:212
AccountID getAccountID(SField const &field) const
Definition STObject.cpp:657
STArray const & getFieldArray(SField const &field) const
Definition STObject.cpp:692
T::value_type at(TypedField< T > const &f) const
Get the value of a field.
Definition STObject.h:1042
std::uint32_t getFieldU32(SField const &field) const
Definition STObject.cpp:615
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:484
static STObject makeInnerObject(SField const &name)
Definition STObject.cpp:95
uint256 getFieldH256(SField const &field) const
Definition STObject.cpp:645
AccountID const account_
Definition Transactor.h:147
ApplyView & view()
Definition Transactor.h:163
ApplyContext & ctx_
Definition Transactor.h:143
T is_same_v
NotTEC checkArray(STArray const &credentials, unsigned maxSize, beast::Journal j)
std::set< std::pair< AccountID, Slice > > makeSorted(STArray const &credentials)
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Definition Indexes.cpp:570
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 maxPermissionedDomainCredentialsArraySize
The maximum number of credentials can be passed in array for permissioned domain.
Definition Protocol.h:110
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
@ tefINTERNAL
Definition TER.h:173
@ tecNO_ENTRY
Definition TER.h:306
@ tecNO_ISSUER
Definition TER.h:299
@ tecDIR_FULL
Definition TER.h:287
@ 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
@ credential
Credentials signature.
@ temMALFORMED
Definition TER.h:87
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:39
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
beast::Journal const j
Definition Transactor.h:42