xrpld
Loading...
Searching...
No Matches
Indexes.cpp
1#include <xrpl/protocol/Indexes.h>
2
3#include <xrpl/basics/Slice.h>
4#include <xrpl/basics/base_uint.h>
5#include <xrpl/basics/safe_cast.h>
6#include <xrpl/beast/utility/instrumentation.h>
7#include <xrpl/protocol/AccountID.h>
8#include <xrpl/protocol/Asset.h>
9#include <xrpl/protocol/Book.h>
10#include <xrpl/protocol/Concepts.h>
11#include <xrpl/protocol/Issue.h>
12#include <xrpl/protocol/LedgerFormats.h>
13#include <xrpl/protocol/MPTIssue.h>
14#include <xrpl/protocol/Protocol.h>
15#include <xrpl/protocol/SField.h>
16#include <xrpl/protocol/STXChainBridge.h>
17#include <xrpl/protocol/SeqProxy.h>
18#include <xrpl/protocol/UintTypes.h>
19#include <xrpl/protocol/digest.h>
20#include <xrpl/protocol/nftPageMask.h>
21
22#include <boost/endian/conversion.hpp>
23
24#include <algorithm>
25#include <array>
26#include <cstdint>
27#include <cstring>
28#include <set>
29#include <utility>
30#include <variant>
31#include <vector>
32
33namespace xrpl {
34
53 Account = 'a',
54 DirNode = 'd',
55 TrustLine = 'r',
56 Offer = 'o',
57 OwnerDir = 'O',
58 BookDir = 'B',
59 SkipList = 's',
60 Escrow = 'u',
63 Ticket = 'T',
66 Check = 'C',
73 Amm = 'A',
74 Bridge = 'H',
77 Did = 'I',
78 Oracle = 'R',
80 MPToken = 't',
83 Delegate = 'E',
84 Vault = 'V',
85 LoanBroker = 'l', // lower-case L
86 Loan = 'L',
87
88 // No longer used or supported. Left here to reserve the space to avoid accidental reuse.
89 Contract [[deprecated]] = 'c',
90 Generator [[deprecated]] = 'g',
91 Nickname [[deprecated]] = 'n',
92};
93
94template <class... Args>
95static uint256
96indexHash(LedgerNameSpace space, Args const&... args)
97{
98 return sha512Half(safeCast<std::uint16_t>(space), args...);
99}
100
102getBookBase(Book const& book)
103{
104 XRPL_ASSERT(isConsistent(book), "xrpl::getBookBase : input is consistent");
105
106 auto getIndexHash = [&book]<typename... Args>(Args... args) {
107 if (book.domain)
108 return indexHash(std::forward<Args>(args)..., *book.domain);
109 return indexHash(std::forward<Args>(args)...);
110 };
111
112 auto const index = std::visit(
113 [&]<ValidIssueType TIn, ValidIssueType TOut>(TIn const& in, TOut const& out) {
115 {
116 return getIndexHash(
117 LedgerNameSpace::BookDir, in.currency, out.currency, in.account, out.account);
118 }
120 {
121 return getIndexHash(
122 LedgerNameSpace::BookDir, in.currency, out.getMptID(), in.account);
123 }
125 {
126 return getIndexHash(
127 LedgerNameSpace::BookDir, in.getMptID(), out.currency, out.account);
128 }
129 else
130 {
131 return getIndexHash(LedgerNameSpace::BookDir, in.getMptID(), out.getMptID());
132 }
133 },
134 book.in.value(),
135 book.out.value());
136
137 // Return with quality 0.
138 auto k = keylet::quality({ltDIR_NODE, index}, 0);
139
140 return k.key;
141}
142
145{
146 static constexpr uint256 kNextQuality(
147 "0000000000000000000000000000000000000000000000010000000000000000");
148 return uBase + kNextQuality;
149}
150
152getQuality(uint256 const& uBase)
153{
154 // VFALCO [base_uint] This assumes a certain storage format
155 return boost::endian::big_to_native(((std::uint64_t*)uBase.end())[-1]);
156}
157
159getTicketIndex(AccountID const& account, std::uint32_t ticketSeq)
160{
161 return indexHash(LedgerNameSpace::Ticket, account, ticketSeq);
162}
163
165getTicketIndex(AccountID const& account, SeqProxy ticketSeq)
166{
167 XRPL_ASSERT(ticketSeq.isTicket(), "xrpl::getTicketIndex : valid input");
168 return getTicketIndex(account, ticketSeq.value());
169}
170
171MPTID
172makeMptID(std::uint32_t sequence, AccountID const& account)
173{
174 MPTID u;
175 sequence = boost::endian::native_to_big(sequence);
176 memcpy(u.data(), &sequence, sizeof(sequence));
177 memcpy(u.data() + sizeof(sequence), account.data(), sizeof(account));
178 return u;
179}
180
181//------------------------------------------------------------------------------
182
183namespace keylet {
184
185Keylet
186account(AccountID const& id) noexcept
187{
188 return Keylet{ltACCOUNT_ROOT, indexHash(LedgerNameSpace::Account, id)};
189}
190
191Keylet
192child(uint256 const& key) noexcept
193{
194 return {ltCHILD, key};
195}
196
197Keylet const&
198skip() noexcept
199{
200 static Keylet const kRet{ltLEDGER_HASHES, indexHash(LedgerNameSpace::SkipList)};
201 return kRet;
202}
203
204Keylet
205skip(LedgerIndex ledger) noexcept
206{
207 return {
208 ltLEDGER_HASHES,
209 indexHash(
210 LedgerNameSpace::SkipList, std::uint32_t(static_cast<std::uint32_t>(ledger) >> 16))};
211}
212
213Keylet const&
214amendments() noexcept
215{
216 static Keylet const kRet{ltAMENDMENTS, indexHash(LedgerNameSpace::Amendments)};
217 return kRet;
218}
219
220Keylet const&
221feeSettings() noexcept
222{
223 static Keylet const kRet{ltFEE_SETTINGS, indexHash(LedgerNameSpace::FeeSettings)};
224 return kRet;
225}
226
227Keylet const&
228negativeUNL() noexcept
229{
230 static Keylet const kRet{ltNEGATIVE_UNL, indexHash(LedgerNameSpace::NegativeUnl)};
231 return kRet;
232}
233
234Keylet
235book(Book const& b)
236{
237 return {ltDIR_NODE, getBookBase(b)};
238}
239
240Keylet
241trustLine(AccountID const& id0, AccountID const& id1, Currency const& currency) noexcept
242{
243 // There is code in TrustSet that calls us with id0 == id1, to allow users
244 // to locate and delete such "weird" trustlines. If we remove that code, we
245 // could enable this assert:
246 // XRPL_ASSERT(id0 != id1, "xrpl::keylet::trustLine : accounts must be
247 // different");
248
249 // A trust line is shared between two accounts; while we typically think
250 // of this as an "issuer" and a "holder" the relationship is actually fully
251 // bidirectional.
252 //
253 // So that we can generate a unique ID for a trust line, regardess of which
254 // side of the line we're looking at, we define a "canonical" order for the
255 // two accounts (smallest then largest) and hash them in that order:
256 auto const accounts = std::minmax(id0, id1);
257
258 return {
259 ltRIPPLE_STATE,
260 indexHash(LedgerNameSpace::TrustLine, accounts.first, accounts.second, currency)};
261}
262
263Keylet
264offer(AccountID const& id, std::uint32_t seq) noexcept
265{
266 return {ltOFFER, indexHash(LedgerNameSpace::Offer, id, seq)};
267}
268
269Keylet
270quality(Keylet const& k, std::uint64_t q) noexcept
271{
272 XRPL_ASSERT(k.type == ltDIR_NODE, "xrpl::keylet::quality : valid input type");
273
274 // Indexes are stored in big endian format: they print as hex as stored.
275 // Most significant bytes are first and the least significant bytes
276 // represent adjacent entries. We place the quality, in big endian format,
277 // in the 8 right most bytes; this way, incrementing goes to the next entry
278 // for indexes.
279 uint256 x = k.key;
280
281 // FIXME This is ugly and we can and should do better...
282 ((std::uint64_t*)x.end())[-1] = boost::endian::native_to_big(q);
283
284 return {ltDIR_NODE, x};
285}
286
287Keylet
288next(Keylet const& k)
289{
290 XRPL_ASSERT(k.type == ltDIR_NODE, "xrpl::keylet::next : valid input type");
291 return {ltDIR_NODE, getQualityNext(k.key)};
292}
293
294Keylet
295ticket(AccountID const& id, std::uint32_t ticketSeq)
296{
297 return {ltTICKET, getTicketIndex(id, ticketSeq)};
298}
299
300Keylet
301ticket(AccountID const& id, SeqProxy ticketSeq)
302{
303 return {ltTICKET, getTicketIndex(id, ticketSeq)};
304}
305
306// This function is presently static, since it's never accessed from anywhere
307// else. If we ever support multiple pages of signer lists, this would be the
308// keylet used to locate them.
309static Keylet
311{
312 return {ltSIGNER_LIST, indexHash(LedgerNameSpace::SignerList, account, page)};
313}
314
315Keylet
317{
318 return signerList(account, 0);
319}
320
321Keylet
322check(AccountID const& id, std::uint32_t seq) noexcept
323{
324 return {ltCHECK, indexHash(LedgerNameSpace::Check, id, seq)};
325}
326
327Keylet
328depositPreauth(AccountID const& owner, AccountID const& preauthorized) noexcept
329{
330 return {ltDEPOSIT_PREAUTH, indexHash(LedgerNameSpace::DepositPreauth, owner, preauthorized)};
331}
332
333// Credentials should be sorted here, use credentials::makeSorted
334Keylet
336 AccountID const& owner,
337 std::set<std::pair<AccountID, Slice>> const& authCreds) noexcept
338{
340 hashes.reserve(authCreds.size());
341 for (auto const& o : authCreds)
342 hashes.emplace_back(sha512Half(o.first, o.second));
343
344 return {
345 ltDEPOSIT_PREAUTH, indexHash(LedgerNameSpace::DepositPreauthCredentials, owner, hashes)};
346}
347
348//------------------------------------------------------------------------------
349
350Keylet
351unchecked(uint256 const& key) noexcept
352{
353 return {ltANY, key};
354}
355
356Keylet
357ownerDir(AccountID const& id) noexcept
358{
359 return {ltDIR_NODE, indexHash(LedgerNameSpace::OwnerDir, id)};
360}
361
362Keylet
363page(uint256 const& key, std::uint64_t index) noexcept
364{
365 if (index == 0)
366 return {ltDIR_NODE, key};
367
368 return {ltDIR_NODE, indexHash(LedgerNameSpace::DirNode, key, index)};
369}
370
371Keylet
372escrow(AccountID const& src, std::uint32_t seq) noexcept
373{
374 return {ltESCROW, indexHash(LedgerNameSpace::Escrow, src, seq)};
375}
376
377Keylet
378payChannel(AccountID const& src, AccountID const& dst, std::uint32_t seq) noexcept
379{
380 return {ltPAYCHAN, indexHash(LedgerNameSpace::XRPPaymentChannel, src, dst, seq)};
381}
382
383Keylet
385{
387 std::memcpy(buf.data(), owner.data(), owner.size());
388 return {ltNFTOKEN_PAGE, uint256::fromRaw(buf)};
389}
390
391Keylet
393{
395 std::memcpy(id.data(), owner.data(), owner.size());
396 return {ltNFTOKEN_PAGE, id};
397}
398
399Keylet
400nftokenPage(Keylet const& k, uint256 const& token)
401{
402 XRPL_ASSERT(k.type == ltNFTOKEN_PAGE, "xrpl::keylet::nftokenPage : valid input type");
403 return {ltNFTOKEN_PAGE, (k.key & ~nft::kPageMask) + (token & nft::kPageMask)};
404}
405
406Keylet
408{
409 return {ltNFTOKEN_OFFER, indexHash(LedgerNameSpace::NftokenOffer, owner, seq)};
410}
411
412Keylet
413nftBuys(uint256 const& id) noexcept
414{
415 return {ltDIR_NODE, indexHash(LedgerNameSpace::NftokenBuyOffers, id)};
416}
417
418Keylet
419nftSells(uint256 const& id) noexcept
420{
421 return {ltDIR_NODE, indexHash(LedgerNameSpace::NftokenSellOffers, id)};
422}
423
424Keylet
425amm(Asset const& asset1, Asset const& asset2) noexcept
426{
427 auto const& [minA, maxA] = std::minmax(asset1, asset2);
428 return std::visit(
429 []<ValidIssueType TIss1, ValidIssueType TIss2>(TIss1 const& issue1, TIss2 const& issue2) {
431 {
432 return amm(indexHash(
434 issue1.account,
435 issue1.currency,
436 issue2.account,
437 issue2.currency));
438 }
440 {
441 return amm(indexHash(
442 LedgerNameSpace::Amm, issue1.account, issue1.currency, issue2.getMptID()));
443 }
445 {
446 return amm(indexHash(
447 LedgerNameSpace::Amm, issue1.getMptID(), issue2.account, issue2.currency));
448 }
450 {
451 return amm(indexHash(LedgerNameSpace::Amm, issue1.getMptID(), issue2.getMptID()));
452 }
453 },
454 minA.value(),
455 maxA.value());
456}
457
458Keylet
459amm(uint256 const& id) noexcept
460{
461 return {ltAMM, id};
462}
463
464Keylet
465delegate(AccountID const& account, AccountID const& authorizedAccount) noexcept
466{
467 return {ltDELEGATE, indexHash(LedgerNameSpace::Delegate, account, authorizedAccount)};
468}
469
470Keylet
472{
473 // A door account can support multiple bridges. On the locking chain
474 // there can only be one bridge per lockingChainCurrency. On the issuing
475 // chain there can only be one bridge per issuingChainCurrency.
476 auto const& issue = bridge.issue(chainType);
477 return {ltBRIDGE, indexHash(LedgerNameSpace::Bridge, bridge.door(chainType), issue.currency)};
478}
479
480Keylet
482{
483 return {
484 ltXCHAIN_OWNED_CLAIM_ID,
485 indexHash(
487 bridge.lockingChainDoor(),
488 bridge.lockingChainIssue(),
489 bridge.issuingChainDoor(),
490 bridge.issuingChainIssue(),
491 seq)};
492}
493
494Keylet
496{
497 return {
498 ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID,
499 indexHash(
501 bridge.lockingChainDoor(),
502 bridge.lockingChainIssue(),
503 bridge.issuingChainDoor(),
504 bridge.issuingChainIssue(),
505 seq)};
506}
507
508Keylet
509did(AccountID const& account) noexcept
510{
511 return {ltDID, indexHash(LedgerNameSpace::Did, account)};
512}
513
514Keylet
515oracle(AccountID const& account, std::uint32_t const& documentID) noexcept
516{
517 return {ltORACLE, indexHash(LedgerNameSpace::Oracle, account, documentID)};
518}
519
520Keylet
521mptokenIssuance(std::uint32_t seq, AccountID const& issuer) noexcept
522{
523 return mptokenIssuance(makeMptID(seq, issuer));
524}
525
526Keylet
527mptokenIssuance(MPTID const& issuanceID) noexcept
528{
529 return {ltMPTOKEN_ISSUANCE, indexHash(LedgerNameSpace::MPTokenIssuance, issuanceID)};
530}
531
532Keylet
533mptoken(MPTID const& issuanceID, AccountID const& holder) noexcept
534{
535 return mptoken(mptokenIssuance(issuanceID).key, holder);
536}
537
538Keylet
539mptoken(uint256 const& issuanceKey, AccountID const& holder) noexcept
540{
541 return {ltMPTOKEN, indexHash(LedgerNameSpace::MPToken, issuanceKey, holder)};
542}
543
544Keylet
545credential(AccountID const& subject, AccountID const& issuer, Slice const& credType) noexcept
546{
547 return {ltCREDENTIAL, indexHash(LedgerNameSpace::Credential, subject, issuer, credType)};
548}
549
550Keylet
551vault(AccountID const& owner, std::uint32_t seq) noexcept
552{
553 return vault(indexHash(LedgerNameSpace::Vault, owner, seq));
554}
555
556Keylet
557loanBroker(AccountID const& owner, std::uint32_t seq) noexcept
558{
560}
561
562Keylet
563loan(uint256 const& loanBrokerID, std::uint32_t loanSeq) noexcept
564{
565 return loan(indexHash(LedgerNameSpace::Loan, loanBrokerID, loanSeq));
566}
567
568Keylet
570{
571 return {ltPERMISSIONED_DOMAIN, indexHash(LedgerNameSpace::PermissionedDomain, account, seq)};
572}
573
574Keylet
575permissionedDomain(uint256 const& domainID) noexcept
576{
577 return {ltPERMISSIONED_DOMAIN, domainID};
578}
579
580} // namespace keylet
581
582} // namespace xrpl
static BaseUInt fromRaw(Container const &c)
Definition base_uint.h:294
iterator end()
Definition base_uint.h:122
pointer data()
Definition base_uint.h:106
static constexpr std::size_t size()
Definition base_uint.h:530
Specifies an order book.
Definition Book.h:16
A type that represents either a sequence value or a ticket value.
Definition SeqProxy.h:36
constexpr bool isTicket() const
Definition SeqProxy.h:74
constexpr std::uint32_t value() const
Definition SeqProxy.h:62
An immutable linear range of bytes.
Definition Slice.h:26
T data(T... args)
T emplace_back(T... args)
T forward(T... args)
T is_same_v
T memcpy(T... args)
T minmax(T... args)
Keylet const & skip() noexcept
The index of the "short" skip list.
Definition Indexes.cpp:198
Keylet quality(Keylet const &k, std::uint64_t q) noexcept
The initial directory page for a specific quality.
Definition Indexes.cpp:270
Keylet next(Keylet const &k)
The directory for the next lower quality.
Definition Indexes.cpp:288
Keylet ticket(AccountID const &id, std::uint32_t ticketSeq)
A ticket belonging to an account.
Definition Indexes.cpp:295
Keylet oracle(AccountID const &account, std::uint32_t const &documentID) noexcept
Definition Indexes.cpp:515
Keylet loanBroker(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:557
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Definition Indexes.cpp:228
Keylet did(AccountID const &account) noexcept
Definition Indexes.cpp:509
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Definition Indexes.cpp:351
Keylet mptokenIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:521
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Definition Indexes.cpp:328
Keylet book(Book const &b)
The beginning of an order book.
Definition Indexes.cpp:235
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Definition Indexes.cpp:372
Keylet bridge(STXChainBridge const &bridge, STXChainBridge::ChainType chainType)
Definition Indexes.cpp:471
Keylet const & feeSettings() noexcept
The (fixed) index of the object containing the ledger fees.
Definition Indexes.cpp:221
Keylet payChannel(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Definition Indexes.cpp:378
Keylet const & amendments() noexcept
The index of the amendment table.
Definition Indexes.cpp:214
Keylet signerList(AccountID const &account) noexcept
A SignerList.
Definition Indexes.cpp:316
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:357
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Definition Indexes.cpp:322
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Definition Indexes.cpp:425
Keylet nftokenPageMin(AccountID const &owner)
NFT page keylets.
Definition Indexes.cpp:384
Keylet loan(uint256 const &loanBrokerID, std::uint32_t loanSeq) noexcept
Definition Indexes.cpp:563
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
Definition Indexes.cpp:264
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Definition Indexes.cpp:192
Keylet nftokenPage(Keylet const &k, uint256 const &token)
Definition Indexes.cpp:400
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:551
Keylet nftokenPageMax(AccountID const &owner)
A keylet for the owner's last possible NFT page.
Definition Indexes.cpp:392
Keylet xChainCreateAccountClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Definition Indexes.cpp:495
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Definition Indexes.cpp:533
Keylet nftSells(uint256 const &id) noexcept
The directory of sell offers for the specified NFT.
Definition Indexes.cpp:419
Keylet nftBuys(uint256 const &id) noexcept
The directory of buy offers for the specified NFT.
Definition Indexes.cpp:413
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Definition Indexes.cpp:465
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:186
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Definition Indexes.cpp:569
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
Definition Indexes.cpp:363
Keylet credential(AccountID const &subject, AccountID const &issuer, Slice const &credType) noexcept
Definition Indexes.cpp:545
Keylet xChainClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Definition Indexes.cpp:481
Keylet nftokenOffer(AccountID const &owner, std::uint32_t seq)
An offer from an account to buy or sell an NFT.
Definition Indexes.cpp:407
Keylet trustLine(AccountID const &id0, AccountID const &id1, Currency const &currency) noexcept
The index of a trust line for a given currency.
Definition Indexes.cpp:241
constexpr uint256 kPageMask(std::string_view("0000000000000000000000000000000000000000ffffffffffffffffffffffff"))
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition digest.h:204
std::uint32_t LedgerIndex
A ledger index.
Definition Protocol.h:259
uint256 getTicketIndex(AccountID const &account, std::uint32_t uSequence)
Definition Indexes.cpp:159
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safeCast(Src s) noexcept
Definition safe_cast.h:21
std::uint64_t getQuality(uint256 const &uBase)
Definition Indexes.cpp:152
BaseUInt< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition UintTypes.h:36
static uint256 indexHash(LedgerNameSpace space, Args const &... args)
Definition Indexes.cpp:96
uint256 getQualityNext(uint256 const &uBase)
Definition Indexes.cpp:144
BaseUInt< 192 > MPTID
MPTID is a 192-bit value representing MPT Issuance ID, which is a concatenation of a 32-bit sequence ...
Definition UintTypes.h:44
LedgerNameSpace
Type-specific prefix for calculating ledger indices.
Definition Indexes.cpp:52
uint256 getBookBase(Book const &book)
Definition Indexes.cpp:102
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:28
bool isConsistent(Asset const &asset)
Definition Asset.h:312
@ ltANY
A special type, matching any ledger entry type.
@ ltCHILD
A special type, matching any ledger type except directory nodes.
BaseUInt< 256 > uint256
Definition base_uint.h:562
MPTID makeMptID(std::uint32_t sequence, AccountID const &account)
Definition Indexes.cpp:172
T reserve(T... args)
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:19
uint256 key
Definition Keylet.h:20
LedgerEntryType type
Definition Keylet.h:21
T visit(T... args)