xrpld
Loading...
Searching...
No Matches
CredentialCreate.cpp
1#include <xrpl/tx/transactors/credentials/CredentialCreate.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/base_uint.h>
5#include <xrpl/core/ServiceRegistry.h>
6#include <xrpl/ledger/ApplyView.h>
7#include <xrpl/ledger/helpers/AccountRootHelpers.h>
8#include <xrpl/ledger/helpers/CredentialHelpers.h> // IWYU pragma: keep
9#include <xrpl/ledger/helpers/DirectoryHelpers.h>
10#include <xrpl/protocol/Feature.h>
11#include <xrpl/protocol/Indexes.h>
12#include <xrpl/protocol/Keylet.h>
13#include <xrpl/protocol/LedgerFormats.h>
14#include <xrpl/protocol/Protocol.h>
15#include <xrpl/protocol/SField.h>
16#include <xrpl/protocol/STAmount.h>
17#include <xrpl/protocol/STLedgerEntry.h>
18#include <xrpl/protocol/STTx.h>
19#include <xrpl/protocol/TER.h>
20#include <xrpl/protocol/TxFlags.h>
21#include <xrpl/protocol/XRPAmount.h>
22#include <xrpl/tx/Transactor.h>
23
24#include <chrono>
25#include <cstdint>
26#include <memory>
27
28namespace xrpl {
29
30/*
31 Credentials
32 ======
33
34 A verifiable credentials (VC
35 https://en.wikipedia.org/wiki/Verifiable_credentials), as defined by the W3C
36 specification (https://www.w3.org/TR/vc-data-model-2.0/), is a
37 secure and tamper-evident way to represent information about a subject, such
38 as an individual, organization, or even an IoT device. These credentials are
39 issued by a trusted entity and can be verified by third parties without
40 directly involving the issuer at all.
41*/
42
43using namespace credentials;
44
45std::uint32_t
47{
48 // 0 means "Allow any flags"
49 return ctx.rules.enabled(fixInvalidTxFlags) ? tfUniversalMask : 0;
50}
51
54{
55 auto const& tx = ctx.tx;
56 auto& j = ctx.j;
57
58 if (!tx[sfSubject])
59 {
60 JLOG(j.trace()) << "Malformed transaction: Invalid Subject";
61 return temMALFORMED;
62 }
63
64 auto const uri = tx[~sfURI];
65 if (uri && (uri->empty() || (uri->size() > kMaxCredentialUriLength)))
66 {
67 JLOG(j.trace()) << "Malformed transaction: invalid size of URI.";
68 return temMALFORMED;
69 }
70
71 auto const credType = tx[sfCredentialType];
72 if (credType.empty() || (credType.size() > kMaxCredentialTypeLength))
73 {
74 JLOG(j.trace()) << "Malformed transaction: invalid size of CredentialType.";
75 return temMALFORMED;
76 }
77
78 return tesSUCCESS;
79}
80
81TER
83{
84 auto const credType(ctx.tx[sfCredentialType]);
85 auto const subject = ctx.tx[sfSubject];
86
87 if (!ctx.view.exists(keylet::account(subject)))
88 {
89 JLOG(ctx.j.trace()) << "Subject doesn't exist.";
90 return tecNO_TARGET;
91 }
92
93 if (ctx.view.exists(keylet::credential(subject, ctx.tx[sfAccount], credType)))
94 {
95 JLOG(ctx.j.trace()) << "Credential already exists.";
96 return tecDUPLICATE;
97 }
98
99 return tesSUCCESS;
100}
101
102TER
104{
105 auto const subject = ctx_.tx[sfSubject];
106 auto const credType(ctx_.tx[sfCredentialType]);
107 Keylet const credentialKey = keylet::credential(subject, accountID_, credType);
108
109 auto const sleCred = std::make_shared<SLE>(credentialKey);
110 if (!sleCred)
111 return tefINTERNAL; // LCOV_EXCL_LINE
112
113 auto const optExp = ctx_.tx[~sfExpiration];
114 if (optExp)
115 {
116 std::uint32_t const closeTime =
117 ctx_.view().header().parentCloseTime.time_since_epoch().count();
118
119 if (closeTime > *optExp)
120 {
121 JLOG(j_.trace()) << "Malformed transaction: "
122 "Expiration time is in the past.";
123 return tecEXPIRED;
124 }
125
126 sleCred->setFieldU32(sfExpiration, *optExp);
127 }
128
129 auto const sleIssuer = view().peek(keylet::account(accountID_));
130 if (!sleIssuer)
131 return tefINTERNAL; // LCOV_EXCL_LINE
132
133 {
134 STAmount const reserve{
135 view().fees().accountReserve(sleIssuer->getFieldU32(sfOwnerCount) + 1)};
136 if (preFeeBalance_ < reserve)
138 }
139
140 sleCred->setAccountID(sfSubject, subject);
141 sleCred->setAccountID(sfIssuer, accountID_);
142 sleCred->setFieldVL(sfCredentialType, credType);
143
144 if (ctx_.tx.isFieldPresent(sfURI))
145 sleCred->setFieldVL(sfURI, ctx_.tx.getFieldVL(sfURI));
146
147 {
148 auto const page = view().dirInsert(
150 JLOG(j_.trace()) << "Adding Credential to owner directory " << to_string(credentialKey.key)
151 << ": " << (page ? "success" : "failure");
152 if (!page)
153 return tecDIR_FULL;
154 sleCred->setFieldU64(sfIssuerNode, *page);
155
156 adjustOwnerCount(view(), sleIssuer, 1, j_);
157 }
158
159 if (subject == accountID_)
160 {
161 sleCred->setFieldU32(sfFlags, lsfAccepted);
162 }
163 else
164 {
165 // Added to both dirs, owned only by issuer. CredentialAccept will transfer ownership to
166 // subject. CredentialDelete will remove from both dirs and decrement 1 ownerCount.
167 auto const page =
168 view().dirInsert(keylet::ownerDir(subject), credentialKey, describeOwnerDir(subject));
169 JLOG(j_.trace()) << "Adding Credential to subject directory "
170 << to_string(credentialKey.key) << ": " << (page ? "success" : "failure");
171 if (!page)
172 return tecDIR_FULL;
173 sleCred->setFieldU64(sfSubjectNode, *page);
174 }
175
176 view().insert(sleCred);
177
178 return tesSUCCESS;
179}
180
181void
183{
184 // No transaction-specific invariants yet (future work).
185}
186
187bool
189 STTx const&,
190 TER,
191 XRPAmount,
192 ReadView const&,
193 beast::Journal const&)
194{
195 // No transaction-specific invariants yet (future work).
196 return true;
197}
198} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:38
Stream trace() const
Severity stream access functions.
Definition Journal.h:291
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.
Definition ApplyView.h:340
static std::uint32_t getFlagsMask(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.
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 NotTEC preflight(PreflightContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
A view into a ledger.
Definition ReadView.h:31
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:171
std::shared_ptr< STLedgerEntry const > const & const_ref
beast::Journal const j_
Definition Transactor.h:118
ApplyView & view()
Definition Transactor.h:136
AccountID const accountID_
Definition Transactor.h:120
XRPAmount preFeeBalance_
Definition Transactor.h:121
ApplyContext & ctx_
Definition Transactor.h:116
T make_shared(T... args)
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:357
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:186
Keylet credential(AccountID const &subject, AccountID const &issuer, Slice const &credType) noexcept
Definition Indexes.cpp:545
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
constexpr std::size_t kMaxCredentialTypeLength
The maximum length of a CredentialType inside a Credential.
Definition Protocol.h:225
@ tefINTERNAL
Definition TER.h:163
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:594
void adjustOwnerCount(ApplyView &view, SLE::ref sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Returns a function that sets the owner on a directory SLE.
constexpr std::size_t kMaxCredentialUriLength
The maximum length of a URI inside a Credential.
Definition Protocol.h:222
@ temMALFORMED
Definition TER.h:73
TERSubset< CanCvtToTER > TER
Definition TER.h:634
@ tecDIR_FULL
Definition TER.h:285
@ tecNO_TARGET
Definition TER.h:302
@ tecEXPIRED
Definition TER.h:312
@ tecINSUFFICIENT_RESERVE
Definition TER.h:305
@ tecDUPLICATE
Definition TER.h:313
constexpr FlagValue tfUniversalMask
Definition TxFlags.h:45
@ tesSUCCESS
Definition TER.h:240
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:19
uint256 key
Definition Keylet.h:20
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:61
ReadView const & view
Definition Transactor.h:64
beast::Journal const j
Definition Transactor.h:69
State information when preflighting a tx.
Definition Transactor.h:18
beast::Journal const j
Definition Transactor.h:25