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 ripple {
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) &&
30 !ctx.tx.isFieldPresent(sfDIDDocument) && !ctx.tx.isFieldPresent(sfData))
31 return temEMPTY_DID;
32
33 if (ctx.tx.isFieldPresent(sfURI) && ctx.tx[sfURI].empty() &&
34 ctx.tx.isFieldPresent(sfDIDDocument) && ctx.tx[sfDIDDocument].empty() &&
35 ctx.tx.isFieldPresent(sfData) && ctx.tx[sfData].empty())
36 return temEMPTY_DID;
37
38 auto isTooLong = [&](auto const& sField, std::size_t length) -> bool {
39 if (auto field = ctx.tx[~sField])
40 return field->length() > length;
41 return false;
42 };
43
44 if (isTooLong(sfURI, maxDIDURILength) ||
45 isTooLong(sfDIDDocument, maxDIDDocumentLength) ||
46 isTooLong(sfData, maxDIDAttestationLength))
47 return temMALFORMED;
48
49 return tesSUCCESS;
50}
51
52TER
54 ApplyContext& ctx,
55 std::shared_ptr<SLE> const& sle,
56 AccountID const& owner)
57{
58 auto const sleAccount = ctx.view().peek(keylet::account(owner));
59 if (!sleAccount)
60 return tefINTERNAL; // LCOV_EXCL_LINE
61
62 // Check reserve availability for new object creation
63 {
64 auto const balance = STAmount((*sleAccount)[sfBalance]).xrp();
65 auto const reserve =
66 ctx.view().fees().accountReserve((*sleAccount)[sfOwnerCount] + 1);
67
68 if (balance < reserve)
70 }
71
72 // Add ledger object to ledger
73 ctx.view().insert(sle);
74
75 // Add ledger object to owner's page
76 {
77 auto page = ctx.view().dirInsert(
78 keylet::ownerDir(owner), sle->key(), describeOwnerDir(owner));
79 if (!page)
80 return tecDIR_FULL; // LCOV_EXCL_LINE
81 (*sle)[sfOwnerNode] = *page;
82 }
83 adjustOwnerCount(ctx.view(), sleAccount, 1, ctx.journal);
84 ctx.view().update(sleAccount);
85
86 return tesSUCCESS;
87}
88
89TER
91{
92 // Edit ledger object if it already exists
93 Keylet const didKeylet = keylet::did(account_);
94 if (auto const sleDID = ctx_.view().peek(didKeylet))
95 {
96 auto update = [&](auto const& sField) {
97 if (auto const field = ctx_.tx[~sField])
98 {
99 if (field->empty())
100 {
101 sleDID->makeFieldAbsent(sField);
102 }
103 else
104 {
105 (*sleDID)[sField] = *field;
106 }
107 }
108 };
109 update(sfURI);
110 update(sfDIDDocument);
111 update(sfData);
112
113 if (!sleDID->isFieldPresent(sfURI) &&
114 !sleDID->isFieldPresent(sfDIDDocument) &&
115 !sleDID->isFieldPresent(sfData))
116 {
117 return tecEMPTY_DID;
118 }
119 ctx_.view().update(sleDID);
120 return tesSUCCESS;
121 }
122
123 // Create new ledger object otherwise
124 auto const sleDID = std::make_shared<SLE>(didKeylet);
125 (*sleDID)[sfAccount] = account_;
126
127 auto set = [&](auto const& sField) {
128 if (auto const field = ctx_.tx[~sField]; field && !field->empty())
129 (*sleDID)[sField] = *field;
130 };
131
132 set(sfURI);
133 set(sfDIDDocument);
134 set(sfData);
135 if (ctx_.view().rules().enabled(fixEmptyDID) &&
136 !sleDID->isFieldPresent(sfURI) &&
137 !sleDID->isFieldPresent(sfDIDDocument) &&
138 !sleDID->isFieldPresent(sfData))
139 {
140 return tecEMPTY_DID;
141 }
142
143 return addSLE(ctx_, sleDID, account_);
144}
145
146NotTEC
148{
149 return tesSUCCESS;
150}
151
152TER
154{
155 auto const sle = ctx.view().peek(sleKeylet);
156 if (!sle)
157 return tecNO_ENTRY;
158
159 return DIDDelete::deleteSLE(ctx.view(), sle, owner, ctx.journal);
160}
161
162TER
164 ApplyView& view,
166 AccountID const owner,
168{
169 // Remove object from owner directory
170 if (!view.dirRemove(
171 keylet::ownerDir(owner), (*sle)[sfOwnerNode], sle->key(), true))
172 {
173 // LCOV_EXCL_START
174 JLOG(j.fatal()) << "Unable to delete DID Token from owner.";
175 return tefBAD_LEDGER;
176 // LCOV_EXCL_STOP
177 }
178
179 auto const sleOwner = view.peek(keylet::account(owner));
180 if (!sleOwner)
181 return tecINTERNAL; // LCOV_EXCL_LINE
182
183 adjustOwnerCount(view, sleOwner, -1, j);
184 view.update(sleOwner);
185
186 // Remove object from ledger
187 view.erase(sle);
188 return tesSUCCESS;
189}
190
191TER
196
197} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:41
Stream fatal() const
Definition Journal.h:333
State information when applying a tx.
ApplyView & view()
beast::Journal const journal
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:124
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 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:300
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual void erase(std::shared_ptr< SLE > const &sle)=0
Remove a peeked SLE.
static NotTEC preflight(PreflightContext const &ctx)
Definition DID.cpp:147
static TER deleteSLE(ApplyContext &ctx, Keylet sleKeylet, AccountID const owner)
Definition DID.cpp:153
TER doApply() override
Definition DID.cpp:192
static NotTEC preflight(PreflightContext const &ctx)
Definition DID.cpp:27
TER doApply() override
Definition DID.cpp:90
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:111
XRPAmount xrp() const
Definition STAmount.cpp:264
bool empty() const
Definition STObject.h:926
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:465
AccountID const account_
Definition Transactor.h:128
ApplyView & view()
Definition Transactor.h:144
ApplyContext & ctx_
Definition Transactor.h:124
T is_same_v
Keylet did(AccountID const &account) noexcept
Definition Indexes.cpp:495
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:165
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:355
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::size_t constexpr maxDIDURILength
The maximum length of a URI inside a DID.
Definition Protocol.h:75
std::size_t constexpr maxDIDAttestationLength
The maximum length of an Attestation inside a DID.
Definition Protocol.h:78
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:1013
TER addSLE(ApplyContext &ctx, std::shared_ptr< SLE > const &sle, AccountID const &owner)
Definition DID.cpp:53
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:72
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition View.cpp:1031
@ tefBAD_LEDGER
Definition TER.h:151
@ tefINTERNAL
Definition TER.h:154
@ tecNO_ENTRY
Definition TER.h:288
@ tecDIR_FULL
Definition TER.h:269
@ tecINTERNAL
Definition TER.h:292
@ tecEMPTY_DID
Definition TER.h:335
@ tecINSUFFICIENT_RESERVE
Definition TER.h:289
@ tesSUCCESS
Definition TER.h:226
TERSubset< CanCvtToTER > TER
Definition TER.h:630
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:590
@ temMALFORMED
Definition TER.h:68
@ temEMPTY_DID
Definition TER.h:119
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