xrpld
Loading...
Searching...
No Matches
CredentialAccept.cpp
1#include <xrpl/tx/transactors/credentials/CredentialAccept.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/ledger/ApplyView.h>
5#include <xrpl/ledger/helpers/AccountRootHelpers.h>
6#include <xrpl/ledger/helpers/CredentialHelpers.h>
7#include <xrpl/ledger/helpers/SponsorHelpers.h>
8#include <xrpl/protocol/AccountID.h>
9#include <xrpl/protocol/Feature.h>
10#include <xrpl/protocol/Indexes.h>
11#include <xrpl/protocol/Keylet.h>
12#include <xrpl/protocol/LedgerFormats.h>
13#include <xrpl/protocol/Protocol.h>
14#include <xrpl/protocol/SField.h>
15#include <xrpl/protocol/STLedgerEntry.h>
16#include <xrpl/protocol/STTx.h>
17#include <xrpl/protocol/TER.h>
18#include <xrpl/protocol/TxFlags.h>
19#include <xrpl/protocol/XRPAmount.h>
20#include <xrpl/tx/Transactor.h>
21
22#include <cstdint>
23namespace xrpl {
24
25using namespace credentials;
26
27std::uint32_t
29{
30 // 0 means "Allow any flags"
31 return ctx.rules.enabled(fixInvalidTxFlags) ? tfUniversalMask : 0;
32}
33
36{
37 if (!ctx.tx[sfIssuer])
38 {
39 JLOG(ctx.j.trace()) << "Malformed transaction: Issuer field zeroed.";
41 }
42
43 auto const credType = ctx.tx[sfCredentialType];
44 if (credType.empty() || (credType.size() > kMaxCredentialTypeLength))
45 {
46 JLOG(ctx.j.trace()) << "Malformed transaction: invalid size of CredentialType.";
47 return temMALFORMED;
48 }
49
50 return tesSUCCESS;
51}
52
53TER
55{
56 AccountID const subject = ctx.tx[sfAccount];
57 AccountID const issuer = ctx.tx[sfIssuer];
58 auto const credType(ctx.tx[sfCredentialType]);
59
60 if (!ctx.view.exists(keylet::account(issuer)))
61 {
62 JLOG(ctx.j.warn()) << "No issuer: " << to_string(issuer);
63 return tecNO_ISSUER;
64 }
65
66 auto const sleCred = ctx.view.read(keylet::credential(subject, issuer, credType));
67 if (!sleCred)
68 {
69 JLOG(ctx.j.warn()) << "No credential: " << to_string(subject) << ", " << to_string(issuer)
70 << ", " << credType;
71 return tecNO_ENTRY;
72 }
73
74 if (sleCred->isFlag(lsfAccepted))
75 {
76 JLOG(ctx.j.warn()) << "Credential already accepted: " << to_string(subject) << ", "
77 << to_string(issuer) << ", " << credType;
78 return tecDUPLICATE;
79 }
80
81 return tesSUCCESS;
82}
83
84TER
86{
87 AccountID const issuer{ctx_.tx[sfIssuer]};
88
89 // Both exist as credential object exist itself (checked in preclaim)
90 auto const sleSubject = view().peek(keylet::account(accountID_));
91 auto const sleIssuer = view().peek(keylet::account(issuer));
92
93 if (!sleSubject || !sleIssuer)
94 return tefINTERNAL; // LCOV_EXCL_LINE
95
96 auto txSponsorSle = getTxReserveSponsor(ctx_.getApplyViewContext());
97 if (!txSponsorSle)
98 return txSponsorSle.error(); // LCOV_EXCL_LINE
99
100 if (auto const ret = checkReserve(
101 ctx_.getApplyViewContext(),
102 sleSubject,
104 *txSponsorSle,
105 {.ownerCountDelta = 1},
106 j_);
107 !isTesSuccess(ret))
108 return ret;
109
110 auto const credType(ctx_.tx[sfCredentialType]);
111 Keylet const credentialKey = keylet::credential(accountID_, issuer, credType);
112 auto const sleCred = view().peek(credentialKey); // Checked in preclaim()
113 if (!sleCred)
114 return tefINTERNAL; // LCOV_EXCL_LINE
115
116 if (checkExpired(*sleCred, view().header().parentCloseTime))
117 {
118 JLOG(j_.trace()) << "Credential is expired: " << sleCred->getText();
119 // delete expired credentials even if the transaction failed
120 auto const err = credentials::deleteSLE(view(), sleCred, j_);
121 return isTesSuccess(err) ? tecEXPIRED : err;
122 }
123
124 sleCred->setFieldU32(sfFlags, lsfAccepted);
125
126 // Release the original creation sponsor from the credential (it covered
127 // the issuer's reserve), then assign the accept tx's sponsor (if any) so
128 // the credential reflects whoever is now covering the subject's reserve.
129 decreaseOwnerCountForObject(view(), sleIssuer, sleCred, 1, j_);
131
132 addSponsorToLedgerEntry(ctx_.getApplyViewContext(), sleCred);
133 increaseOwnerCount(ctx_.getApplyViewContext(), sleSubject, 1, j_);
134 view().update(sleCred);
135
136 return tesSUCCESS;
137}
138
139void
141{
142 // No transaction-specific invariants yet (future work).
143}
144
145bool
147 STTx const&,
148 TER,
149 XRPAmount,
150 ReadView const&,
151 beast::Journal const&)
152{
153 // No transaction-specific invariants yet (future work).
154 return true;
155}
156} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
Stream trace() const
Severity stream access functions.
Definition Journal.h:338
Stream warn() const
Definition Journal.h:356
virtual SLE::pointer peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual void update(SLE::ref sle)=0
Indicate changes to a peeked SLE.
void visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override
Inspect a single ledger entry modified by this transaction.
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 preclaim(PreclaimContext const &ctx)
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
A view into a ledger.
Definition ReadView.h:41
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.
Definition Rules.cpp:180
std::shared_ptr< STLedgerEntry const > const & const_ref
beast::Journal const j_
Definition Transactor.h:155
ApplyView & view()
Definition Transactor.h:175
AccountID const accountID_
Definition Transactor.h:157
XRPAmount preFeeBalance_
Definition Transactor.h:158
ApplyContext & ctx_
Definition Transactor.h:153
TER deleteSLE(ApplyView &view, SLE::ref sleCredential, beast::Journal j)
bool checkExpired(SLE const &sleCredential, NetClock::time_point const &closed)
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:198
Keylet credential(AccountID const &subject, AccountID const &issuer, Slice const &credType) noexcept
Definition Indexes.cpp:555
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
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.
constexpr std::size_t kMaxCredentialTypeLength
The maximum length of a CredentialType inside a Credential.
Definition Protocol.h:275
@ tefINTERNAL
Definition TER.h:165
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:651
std::expected< SLE::pointer, TER > getTxReserveSponsor(ApplyViewContext ctx)
Return a mutable SLE for the transaction's reserve sponsor account.
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
Definition TER.h:607
void removeSponsorFromLedgerEntry(SLE::ref sle, SF_ACCOUNT const &field=sfSponsor)
Remove the reserve sponsor field from a ledger entry.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:34
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.
@ temMALFORMED
Definition TER.h:75
@ temINVALID_ACCOUNT_ID
Definition TER.h:107
bool isTesSuccess(TER x) noexcept
Definition TER.h:676
TERSubset< CanCvtToTER > TER
Definition TER.h:647
@ tecNO_ENTRY
Definition TER.h:309
@ tecEXPIRED
Definition TER.h:317
@ tecNO_ISSUER
Definition TER.h:302
@ tecDUPLICATE
Definition TER.h:318
constexpr FlagValue tfUniversalMask
Definition TxFlags.h:46
@ tesSUCCESS
Definition TER.h:245
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:20
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:83
ReadView const & view
Definition Transactor.h:86
beast::Journal const j
Definition Transactor.h:91
State information when preflighting a tx.
Definition Transactor.h:38
beast::Journal const j
Definition Transactor.h:45