rippled
Loading...
Searching...
No Matches
DIDSet.cpp
1#include <xrpl/basics/Log.h>
2#include <xrpl/ledger/ApplyView.h>
3#include <xrpl/ledger/helpers/AccountRootHelpers.h>
4#include <xrpl/ledger/helpers/DirectoryHelpers.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/Indexes.h>
7#include <xrpl/protocol/TxFlags.h>
8#include <xrpl/tx/transactors/did/DIDSet.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) &&
30 !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) || isTooLong(sfDIDDocument, maxDIDDocumentLength) ||
45 isTooLong(sfData, maxDIDDataLength))
46 return temMALFORMED;
47
48 return tesSUCCESS;
49}
50
51static TER
52addSLE(ApplyContext& ctx, std::shared_ptr<SLE> const& sle, AccountID const& owner)
53{
54 auto const sleAccount = ctx.view().peek(keylet::account(owner));
55 if (!sleAccount)
56 return tefINTERNAL; // LCOV_EXCL_LINE
57
58 // Check reserve availability for new object creation
59 {
60 auto const balance = STAmount((*sleAccount)[sfBalance]).xrp();
61 auto const reserve = ctx.view().fees().accountReserve((*sleAccount)[sfOwnerCount] + 1);
62
63 if (balance < reserve)
65 }
66
67 // Add ledger object to ledger
68 ctx.view().insert(sle);
69
70 // Add ledger object to owner's page
71 {
72 auto page =
73 ctx.view().dirInsert(keylet::ownerDir(owner), sle->key(), describeOwnerDir(owner));
74 if (!page)
75 return tecDIR_FULL; // LCOV_EXCL_LINE
76 (*sle)[sfOwnerNode] = *page;
77 }
78 adjustOwnerCount(ctx.view(), sleAccount, 1, ctx.journal);
79 ctx.view().update(sleAccount);
80
81 return tesSUCCESS;
82}
83
84TER
86{
87 // Edit ledger object if it already exists
88 Keylet const didKeylet = keylet::did(account_);
89 if (auto const sleDID = ctx_.view().peek(didKeylet))
90 {
91 auto update = [&](auto const& sField) {
92 if (auto const field = ctx_.tx[~sField])
93 {
94 if (field->empty())
95 {
96 sleDID->makeFieldAbsent(sField);
97 }
98 else
99 {
100 (*sleDID)[sField] = *field;
101 }
102 }
103 };
104 update(sfURI);
105 update(sfDIDDocument);
106 update(sfData);
107
108 if (!sleDID->isFieldPresent(sfURI) && !sleDID->isFieldPresent(sfDIDDocument) &&
109 !sleDID->isFieldPresent(sfData))
110 {
111 return tecEMPTY_DID;
112 }
113 ctx_.view().update(sleDID);
114 return tesSUCCESS;
115 }
116
117 // Create new ledger object otherwise
118 auto const sleDID = std::make_shared<SLE>(didKeylet);
119 (*sleDID)[sfAccount] = account_;
120
121 auto set = [&](auto const& sField) {
122 if (auto const field = ctx_.tx[~sField]; field && !field->empty())
123 (*sleDID)[sField] = *field;
124 };
125
126 set(sfURI);
127 set(sfDIDDocument);
128 set(sfData);
129 if (ctx_.view().rules().enabled(fixEmptyDID) && !sleDID->isFieldPresent(sfURI) &&
130 !sleDID->isFieldPresent(sfDIDDocument) && !sleDID->isFieldPresent(sfData))
131 {
132 return tecEMPTY_DID;
133 }
134
135 return addSLE(ctx_, sleDID, account_);
136}
137
138} // namespace xrpl
State information when applying a tx.
STTx const & tx
beast::Journal const journal
ApplyView & view()
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to 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:289
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
TER doApply() override
Definition DIDSet.cpp:85
static NotTEC preflight(PreflightContext const &ctx)
Definition DIDSet.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:120
XRPAmount xrp() const
Definition STAmount.cpp:261
bool empty() const
Definition STObject.h:953
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:456
AccountID const account_
Definition Transactor.h:116
ApplyContext & ctx_
Definition Transactor.h:112
T is_same_v
Keylet did(AccountID const &account) noexcept
Definition Indexes.cpp:462
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:336
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:165
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
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
@ tefINTERNAL
Definition TER.h:153
std::size_t constexpr maxDIDDataLength
The maximum length of an Attestation inside a DID.
Definition Protocol.h:212
TERSubset< CanCvtToTER > TER
Definition TER.h:622
void adjustOwnerCount(ApplyView &view, std::shared_ptr< SLE > const &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.
static TER addSLE(ApplyContext &ctx, std::shared_ptr< SLE > const &sle, AccountID const &owner)
Definition DIDSet.cpp:52
@ temEMPTY_DID
Definition TER.h:118
@ temMALFORMED
Definition TER.h:67
@ tecDIR_FULL
Definition TER.h:268
@ tecEMPTY_DID
Definition TER.h:334
@ tecINSUFFICIENT_RESERVE
Definition TER.h:288
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:582
@ tesSUCCESS
Definition TER.h:225
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
State information when preflighting a tx.
Definition Transactor.h:14