rippled
Loading...
Searching...
No Matches
DID.cpp
1#include <xrpld/app/tx/detail/DID.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/ledger/ApplyView.h>
5#include <xrpl/ledger/View.h>
6#include <xrpl/protocol/Feature.h>
7#include <xrpl/protocol/Indexes.h>
8#include <xrpl/protocol/TxFlags.h>
9
10namespace xrpl {
11
12/*
13 DID
14 ======
15
16 Decentralized Identifiers (DIDs) are a new type of identifier that enable
17 verifiable, self-sovereign digital identity and are designed to be
18 compatible with any distributed ledger or network. This implementation
19 conforms to the requirements specified in the DID v1.0 specification
20 currently recommended by the W3C Credentials Community Group
21 (https://www.w3.org/TR/did-core/).
22*/
23
24//------------------------------------------------------------------------------
25
28{
29 if (!ctx.tx.isFieldPresent(sfURI) && !ctx.tx.isFieldPresent(sfDIDDocument) && !ctx.tx.isFieldPresent(sfData))
30 return temEMPTY_DID;
31
32 if (ctx.tx.isFieldPresent(sfURI) && ctx.tx[sfURI].empty() && ctx.tx.isFieldPresent(sfDIDDocument) &&
33 ctx.tx[sfDIDDocument].empty() && ctx.tx.isFieldPresent(sfData) && ctx.tx[sfData].empty())
34 return temEMPTY_DID;
35
36 auto isTooLong = [&](auto const& sField, std::size_t length) -> bool {
37 if (auto field = ctx.tx[~sField])
38 return field->length() > length;
39 return false;
40 };
41
42 if (isTooLong(sfURI, maxDIDURILength) || isTooLong(sfDIDDocument, maxDIDDocumentLength) ||
43 isTooLong(sfData, maxDIDAttestationLength))
44 return temMALFORMED;
45
46 return tesSUCCESS;
47}
48
49TER
50addSLE(ApplyContext& ctx, std::shared_ptr<SLE> const& sle, AccountID const& owner)
51{
52 auto const sleAccount = ctx.view().peek(keylet::account(owner));
53 if (!sleAccount)
54 return tefINTERNAL; // LCOV_EXCL_LINE
55
56 // Check reserve availability for new object creation
57 {
58 auto const balance = STAmount((*sleAccount)[sfBalance]).xrp();
59 auto const reserve = ctx.view().fees().accountReserve((*sleAccount)[sfOwnerCount] + 1);
60
61 if (balance < reserve)
63 }
64
65 // Add ledger object to ledger
66 ctx.view().insert(sle);
67
68 // Add ledger object to owner's page
69 {
70 auto page = ctx.view().dirInsert(keylet::ownerDir(owner), sle->key(), describeOwnerDir(owner));
71 if (!page)
72 return tecDIR_FULL; // LCOV_EXCL_LINE
73 (*sle)[sfOwnerNode] = *page;
74 }
75 adjustOwnerCount(ctx.view(), sleAccount, 1, ctx.journal);
76 ctx.view().update(sleAccount);
77
78 return tesSUCCESS;
79}
80
81TER
83{
84 // Edit ledger object if it already exists
85 Keylet const didKeylet = keylet::did(account_);
86 if (auto const sleDID = ctx_.view().peek(didKeylet))
87 {
88 auto update = [&](auto const& sField) {
89 if (auto const field = ctx_.tx[~sField])
90 {
91 if (field->empty())
92 {
93 sleDID->makeFieldAbsent(sField);
94 }
95 else
96 {
97 (*sleDID)[sField] = *field;
98 }
99 }
100 };
101 update(sfURI);
102 update(sfDIDDocument);
103 update(sfData);
104
105 if (!sleDID->isFieldPresent(sfURI) && !sleDID->isFieldPresent(sfDIDDocument) && !sleDID->isFieldPresent(sfData))
106 {
107 return tecEMPTY_DID;
108 }
109 ctx_.view().update(sleDID);
110 return tesSUCCESS;
111 }
112
113 // Create new ledger object otherwise
114 auto const sleDID = std::make_shared<SLE>(didKeylet);
115 (*sleDID)[sfAccount] = account_;
116
117 auto set = [&](auto const& sField) {
118 if (auto const field = ctx_.tx[~sField]; field && !field->empty())
119 (*sleDID)[sField] = *field;
120 };
121
122 set(sfURI);
123 set(sfDIDDocument);
124 set(sfData);
125 if (ctx_.view().rules().enabled(fixEmptyDID) && !sleDID->isFieldPresent(sfURI) &&
126 !sleDID->isFieldPresent(sfDIDDocument) && !sleDID->isFieldPresent(sfData))
127 {
128 return tecEMPTY_DID;
129 }
130
131 return addSLE(ctx_, sleDID, account_);
132}
133
134NotTEC
136{
137 return tesSUCCESS;
138}
139
140TER
142{
143 auto const sle = ctx.view().peek(sleKeylet);
144 if (!sle)
145 return tecNO_ENTRY;
146
147 return DIDDelete::deleteSLE(ctx.view(), sle, owner, ctx.journal);
148}
149
150TER
152{
153 // Remove object from owner directory
154 if (!view.dirRemove(keylet::ownerDir(owner), (*sle)[sfOwnerNode], sle->key(), true))
155 {
156 // LCOV_EXCL_START
157 JLOG(j.fatal()) << "Unable to delete DID Token from owner.";
158 return tefBAD_LEDGER;
159 // LCOV_EXCL_STOP
160 }
161
162 auto const sleOwner = view.peek(keylet::account(owner));
163 if (!sleOwner)
164 return tecINTERNAL; // LCOV_EXCL_LINE
165
166 adjustOwnerCount(view, sleOwner, -1, j);
167 view.update(sleOwner);
168
169 // Remove object from ledger
170 view.erase(sle);
171 return tesSUCCESS;
172}
173
174TER
179
180} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:41
Stream fatal() const
Definition Journal.h:325
State information when applying a tx.
STTx const & tx
beast::Journal const journal
ApplyView & view()
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:115
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 erase(std::shared_ptr< SLE > const &sle)=0
Remove 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:284
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
static NotTEC preflight(PreflightContext const &ctx)
Definition DID.cpp:135
TER doApply() override
Definition DID.cpp:175
static TER deleteSLE(ApplyContext &ctx, Keylet sleKeylet, AccountID const owner)
Definition DID.cpp:141
TER doApply() override
Definition DID.cpp:82
static NotTEC preflight(PreflightContext const &ctx)
Definition DID.cpp:27
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:118
XRPAmount xrp() const
Definition STAmount.cpp:249
bool empty() const
Definition STObject.h:940
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:439
AccountID const account_
Definition Transactor.h:113
ApplyView & view()
Definition Transactor.h:129
ApplyContext & ctx_
Definition Transactor.h:109
T is_same_v
Keylet did(AccountID const &account) noexcept
Definition Indexes.cpp:450
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:325
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:160
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
std::size_t constexpr maxDIDDocumentLength
The maximum length of a Data element inside a DID.
Definition Protocol.h:206
std::size_t constexpr maxDIDURILength
The maximum length of a URI inside a DID.
Definition Protocol.h:209
@ tefBAD_LEDGER
Definition TER.h:151
@ tefINTERNAL
Definition TER.h:154
TERSubset< CanCvtToTER > TER
Definition TER.h:621
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:941
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition View.cpp:955
TER addSLE(ApplyContext &ctx, std::shared_ptr< SLE > const &sle, AccountID const &owner)
Definition DID.cpp:50
@ temEMPTY_DID
Definition TER.h:119
@ temMALFORMED
Definition TER.h:68
@ tecDIR_FULL
Definition TER.h:269
@ tecNO_ENTRY
Definition TER.h:288
@ tecEMPTY_DID
Definition TER.h:335
@ tecINTERNAL
Definition TER.h:292
@ tecINSUFFICIENT_RESERVE
Definition TER.h:289
std::size_t constexpr maxDIDAttestationLength
The maximum length of an Attestation inside a DID.
Definition Protocol.h:212
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:581
@ tesSUCCESS
Definition TER.h:226
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:20
State information when preflighting a tx.
Definition Transactor.h:16