1#include <xrpl/tx/transactors/payment/DepositPreauth.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/Slice.h>
5#include <xrpl/basics/base_uint.h>
6#include <xrpl/core/ServiceRegistry.h>
7#include <xrpl/ledger/helpers/AccountRootHelpers.h>
8#include <xrpl/ledger/helpers/CredentialHelpers.h>
9#include <xrpl/ledger/helpers/DirectoryHelpers.h>
10#include <xrpl/ledger/helpers/SponsorHelpers.h>
11#include <xrpl/protocol/AccountID.h>
12#include <xrpl/protocol/Feature.h>
13#include <xrpl/protocol/Indexes.h>
14#include <xrpl/protocol/Keylet.h>
15#include <xrpl/protocol/Protocol.h>
16#include <xrpl/protocol/SField.h>
17#include <xrpl/protocol/STArray.h>
18#include <xrpl/protocol/STLedgerEntry.h>
19#include <xrpl/protocol/STTx.h>
20#include <xrpl/protocol/TER.h>
21#include <xrpl/protocol/XRPAmount.h>
22#include <xrpl/tx/Transactor.h>
36 bool const unauthArrPresent = ctx.
tx.
isFieldPresent(sfUnauthorizeCredentials);
37 bool const authCredPresent = authArrPresent || unauthArrPresent;
39 return !authCredPresent || ctx.
rules.
enabled(featureCredentials);
46 bool const unauthArrPresent = ctx.
tx.
isFieldPresent(sfUnauthorizeCredentials);
47 int const authCredPresent =
48 static_cast<int>(authArrPresent) +
static_cast<int>(unauthArrPresent);
50 auto const optAuth = ctx.
tx[~sfAuthorize];
51 auto const optUnauth = ctx.
tx[~sfUnauthorize];
52 int const authPresent =
53 static_cast<int>(optAuth.has_value()) +
static_cast<int>(optUnauth.has_value());
55 if (authPresent + authCredPresent != 1)
58 JLOG(ctx.
j.
trace()) <<
"Malformed transaction: "
59 "Invalid Authorize and Unauthorize field combination.";
67 AccountID const& target(optAuth ? *optAuth : *optUnauth);
70 JLOG(ctx.
j.
trace()) <<
"Malformed transaction: Authorized or Unauthorized "
76 if (optAuth && (target == ctx.
tx[sfAccount]))
78 JLOG(ctx.
j.
trace()) <<
"Malformed transaction: Attempting to DepositPreauth self.";
86 authArrPresent ? sfAuthorizeCredentials : sfUnauthorizeCredentials),
112 JLOG(ctx.
j.
debug()) <<
"Authorized account is a pseudo-account.";
131 for (
auto const& o : authCred)
133 auto const& issuer = o[sfIssuer];
136 auto [it, ins] = sorted.
emplace(issuer, o[sfCredentialType]);
161 auto applyViewContext =
ctx_.getApplyViewContext();
162 if (
ctx_.tx.isFieldPresent(sfAuthorize))
182 slePreauth->setAccountID(sfAccount,
accountID_);
183 slePreauth->setAccountID(sfAuthorize, auth);
189 JLOG(
j_.trace()) <<
"Adding DepositPreauth to owner directory "
190 <<
to_string(preauthKeylet.
key) <<
": " << (page ?
"success" :
"failure");
195 slePreauth->setFieldU64(sfOwnerNode, *page);
201 else if (
ctx_.tx.isFieldPresent(sfUnauthorize))
207 else if (
ctx_.tx.isFieldPresent(sfAuthorizeCredentials))
224 auto const sortedTX =
226 STArray sortedLE(sfAuthorizeCredentials, sortedTX.size());
227 for (
auto const& p : sortedTX)
230 cred.setAccountID(sfIssuer, p.first);
231 cred.setFieldVL(sfCredentialType, p.second);
240 slePreauth->setAccountID(sfAccount,
accountID_);
241 slePreauth->peekFieldArray(sfAuthorizeCredentials) = std::move(sortedLE);
248 JLOG(
j_.trace()) <<
"Adding DepositPreauth to owner directory " <<
to_string(preauthKey.
key)
249 <<
": " << (page ?
"success" :
"failure");
254 slePreauth->setFieldU64(sfOwnerNode, *page);
260 else if (
ctx_.tx.isFieldPresent(sfUnauthorizeCredentials))
277 JLOG(j.
warn()) <<
"Selected DepositPreauth does not exist.";
281 AccountID const account{(*slePreauth)[sfAccount]};
286 JLOG(j.
fatal()) <<
"Unable to delete DepositPreauth from owner.";
298 view.erase(slePreauth);
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
Writeable view to a ledger, for applying a transaction.
virtual SLE::pointer peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual void insert(SLE::ref sle)=0
Insert a new state SLE.
std::optional< std::uint64_t > dirInsert(Keylet const &directory, uint256 const &key, std::function< void(SLE::ref)> const &describe)
Insert an entry to a directory.
bool finalizeInvariants(STTx const &tx, TER result, XRPAmount fee, ReadView const &view, beast::Journal const &j) override
Check transaction-specific post-conditions after all entries have been visited.
static TER removeFromLedger(ApplyView &view, uint256 const &delIndex, beast::Journal j)
static NotTEC preflight(PreflightContext const &ctx)
static bool checkExtraFeatures(PreflightContext const &ctx)
void visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override
Inspect a single ledger entry modified by this transaction.
static TER preclaim(PreclaimContext const &ctx)
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
void pushBack(STObject const &object)
std::shared_ptr< STLedgerEntry const > const & const_ref
STArray const & getFieldArray(SField const &field) const
bool isFieldPresent(SField const &field) const
static STObject makeInnerObject(SField const &name)
AccountID const accountID_
std::set< std::pair< AccountID, Slice > > makeSorted(STArray const &credentials)
NotTEC checkArray(STArray const &credentials, unsigned maxSize, beast::Journal j)
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet account(AccountID const &id) noexcept
AccountID root.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
void decreaseOwnerCountForObject(ApplyView &view, SLE::ref accountSle, SLE::ref objectSle, std::uint32_t count, beast::Journal j)
Decrease owner-count fields for an existing ledger object.
void increaseOwnerCount(ApplyView &view, SLE::ref accountSle, SLE::ref sponsorSle, std::uint32_t count, beast::Journal j)
Increase owner-count fields when the caller supplies the sponsor.
std::string to_string(BaseUInt< Bits, Tag > const &a)
void addSponsorToLedgerEntry(SLE::ref sle, SLE::const_ref sponsorSle, SF_ACCOUNT const &field=sfSponsor)
Stamp a reserve sponsor onto a ledger entry using an explicit sponsor SLE.
TERSubset< CanCvtToNotTEC > NotTEC
constexpr std::size_t kMaxCredentialsArraySize
The maximum number of credentials can be passed in array.
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Returns a function that sets the owner on a directory SLE.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
TER checkReserve(ApplyViewContext ctx, SLE::const_ref accSle, XRPAmount accBalance, SLE::const_ref sponsorSle, Adjustment adj, beast::Journal j, TER insufReserveCode=tecINSUFFICIENT_RESERVE)
Check if an account has sufficient reserve.
bool isTesSuccess(TER x) noexcept
TERSubset< CanCvtToTER > TER
bool isPseudoAccount(SLE::const_pointer sleAcct, std::set< SField const * > const &pseudoFieldFilter={})
Returns true if and only if sleAcct is a pseudo-account or specific pseudo-accounts in pseudoFieldFil...
A pair of SHAMap key and LedgerEntryType.
State information when determining if a tx is likely to claim a fee.
State information when preflighting a tx.