rippled
Loading...
Searching...
No Matches
Indexes.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpl/basics/Slice.h>
21#include <xrpl/basics/base_uint.h>
22#include <xrpl/basics/safe_cast.h>
23#include <xrpl/beast/utility/instrumentation.h>
24#include <xrpl/protocol/AccountID.h>
25#include <xrpl/protocol/Asset.h>
26#include <xrpl/protocol/Book.h>
27#include <xrpl/protocol/Indexes.h>
28#include <xrpl/protocol/LedgerFormats.h>
29#include <xrpl/protocol/Protocol.h>
30#include <xrpl/protocol/SField.h>
31#include <xrpl/protocol/STXChainBridge.h>
32#include <xrpl/protocol/SeqProxy.h>
33#include <xrpl/protocol/UintTypes.h>
34#include <xrpl/protocol/digest.h>
35#include <xrpl/protocol/nftPageMask.h>
36
37#include <boost/endian/conversion.hpp>
38
39#include <algorithm>
40#include <array>
41#include <cstdint>
42#include <cstring>
43#include <set>
44#include <utility>
45#include <vector>
46
47namespace ripple {
48
67 ACCOUNT = 'a',
68 DIR_NODE = 'd',
69 TRUST_LINE = 'r',
70 OFFER = 'o',
71 OWNER_DIR = 'O',
72 BOOK_DIR = 'B',
73 SKIP_LIST = 's',
74 ESCROW = 'u',
75 AMENDMENTS = 'f',
76 FEE_SETTINGS = 'e',
77 TICKET = 'T',
78 SIGNER_LIST = 'S',
80 CHECK = 'C',
81 DEPOSIT_PREAUTH = 'p',
83 NEGATIVE_UNL = 'N',
84 NFTOKEN_OFFER = 'q',
87 AMM = 'A',
88 BRIDGE = 'H',
89 XCHAIN_CLAIM_ID = 'Q',
91 DID = 'I',
92 ORACLE = 'R',
93 MPTOKEN_ISSUANCE = '~',
94 MPTOKEN = 't',
95 CREDENTIAL = 'D',
97 DELEGATE = 'E',
98 VAULT = 'V',
99
100 // No longer used or supported. Left here to reserve the space
101 // to avoid accidental reuse.
102 CONTRACT [[deprecated]] = 'c',
103 GENERATOR [[deprecated]] = 'g',
104 NICKNAME [[deprecated]] = 'n',
105};
106
107template <class... Args>
108static uint256
109indexHash(LedgerNameSpace space, Args const&... args)
110{
111 return sha512Half(safe_cast<std::uint16_t>(space), args...);
112}
113
115getBookBase(Book const& book)
116{
117 XRPL_ASSERT(
118 isConsistent(book), "ripple::getBookBase : input is consistent");
119
120 auto const index = book.domain ? indexHash(
122 book.in.currency,
123 book.out.currency,
124 book.in.account,
125 book.out.account,
126 *(book.domain))
127 : indexHash(
129 book.in.currency,
130 book.out.currency,
131 book.in.account,
132 book.out.account);
133
134 // Return with quality 0.
135 auto k = keylet::quality({ltDIR_NODE, index}, 0);
136
137 return k.key;
138}
139
142{
143 static constexpr uint256 nextq(
144 "0000000000000000000000000000000000000000000000010000000000000000");
145 return uBase + nextq;
146}
147
149getQuality(uint256 const& uBase)
150{
151 // VFALCO [base_uint] This assumes a certain storage format
152 return boost::endian::big_to_native(((std::uint64_t*)uBase.end())[-1]);
153}
154
156getTicketIndex(AccountID const& account, std::uint32_t ticketSeq)
157{
158 return indexHash(
159 LedgerNameSpace::TICKET, account, std::uint32_t(ticketSeq));
160}
161
163getTicketIndex(AccountID const& account, SeqProxy ticketSeq)
164{
165 XRPL_ASSERT(ticketSeq.isTicket(), "ripple::getTicketIndex : valid input");
166 return getTicketIndex(account, ticketSeq.value());
167}
168
169MPTID
170makeMptID(std::uint32_t sequence, AccountID const& account)
171{
172 MPTID u;
173 sequence = boost::endian::native_to_big(sequence);
174 memcpy(u.data(), &sequence, sizeof(sequence));
175 memcpy(u.data() + sizeof(sequence), account.data(), sizeof(account));
176 return u;
177}
178
179//------------------------------------------------------------------------------
180
181namespace keylet {
182
183Keylet
184account(AccountID const& id) noexcept
185{
186 return Keylet{ltACCOUNT_ROOT, indexHash(LedgerNameSpace::ACCOUNT, id)};
187}
188
189Keylet
190child(uint256 const& key) noexcept
191{
192 return {ltCHILD, key};
193}
194
195Keylet const&
196skip() noexcept
197{
198 static Keylet const ret{
199 ltLEDGER_HASHES, indexHash(LedgerNameSpace::SKIP_LIST)};
200 return ret;
201}
202
203Keylet
204skip(LedgerIndex ledger) noexcept
205{
206 return {
207 ltLEDGER_HASHES,
208 indexHash(
210 std::uint32_t(static_cast<std::uint32_t>(ledger) >> 16))};
211}
212
213Keylet const&
214amendments() noexcept
215{
216 static Keylet const ret{
218 return ret;
219}
220
221Keylet const&
222fees() noexcept
223{
224 static Keylet const ret{
226 return ret;
227}
228
229Keylet const&
230negativeUNL() noexcept
231{
232 static Keylet const ret{
234 return ret;
235}
236
237Keylet
239{
240 return {ltDIR_NODE, getBookBase(b)};
241}
242
243Keylet
245 AccountID const& id0,
246 AccountID const& id1,
247 Currency const& currency) noexcept
248{
249 // There is code in SetTrust that calls us with id0 == id1, to allow users
250 // to locate and delete such "weird" trustlines. If we remove that code, we
251 // could enable this assert:
252 // XRPL_ASSERT(id0 != id1, "ripple::keylet::line : accounts must be
253 // different");
254
255 // A trust line is shared between two accounts; while we typically think
256 // of this as an "issuer" and a "holder" the relationship is actually fully
257 // bidirectional.
258 //
259 // So that we can generate a unique ID for a trust line, regardess of which
260 // side of the line we're looking at, we define a "canonical" order for the
261 // two accounts (smallest then largest) and hash them in that order:
262 auto const accounts = std::minmax(id0, id1);
263
264 return {
265 ltRIPPLE_STATE,
266 indexHash(
268 accounts.first,
269 accounts.second,
270 currency)};
271}
272
273Keylet
274offer(AccountID const& id, std::uint32_t seq) noexcept
275{
276 return {ltOFFER, indexHash(LedgerNameSpace::OFFER, id, seq)};
277}
278
279Keylet
280quality(Keylet const& k, std::uint64_t q) noexcept
281{
282 XRPL_ASSERT(
283 k.type == ltDIR_NODE, "ripple::keylet::quality : valid input type");
284
285 // Indexes are stored in big endian format: they print as hex as stored.
286 // Most significant bytes are first and the least significant bytes
287 // represent adjacent entries. We place the quality, in big endian format,
288 // in the 8 right most bytes; this way, incrementing goes to the next entry
289 // for indexes.
290 uint256 x = k.key;
291
292 // FIXME This is ugly and we can and should do better...
293 ((std::uint64_t*)x.end())[-1] = boost::endian::native_to_big(q);
294
295 return {ltDIR_NODE, x};
296}
297
298Keylet
300{
301 XRPL_ASSERT(
302 k.type == ltDIR_NODE,
303 "ripple::keylet::next_t::operator() : valid input type");
304 return {ltDIR_NODE, getQualityNext(k.key)};
305}
306
307Keylet
309{
310 return {ltTICKET, getTicketIndex(id, ticketSeq)};
311}
312
313Keylet
314ticket_t::operator()(AccountID const& id, SeqProxy ticketSeq) const
315{
316 return {ltTICKET, getTicketIndex(id, ticketSeq)};
317}
318
319// This function is presently static, since it's never accessed from anywhere
320// else. If we ever support multiple pages of signer lists, this would be the
321// keylet used to locate them.
322static Keylet
323signers(AccountID const& account, std::uint32_t page) noexcept
324{
325 return {
326 ltSIGNER_LIST, indexHash(LedgerNameSpace::SIGNER_LIST, account, page)};
327}
328
329Keylet
330signers(AccountID const& account) noexcept
331{
332 return signers(account, 0);
333}
334
335Keylet
336check(AccountID const& id, std::uint32_t seq) noexcept
337{
338 return {ltCHECK, indexHash(LedgerNameSpace::CHECK, id, seq)};
339}
340
341Keylet
342depositPreauth(AccountID const& owner, AccountID const& preauthorized) noexcept
343{
344 return {
345 ltDEPOSIT_PREAUTH,
346 indexHash(LedgerNameSpace::DEPOSIT_PREAUTH, owner, preauthorized)};
347}
348
349// Credentials should be sorted here, use credentials::makeSorted
350Keylet
352 AccountID const& owner,
353 std::set<std::pair<AccountID, Slice>> const& authCreds) noexcept
354{
356 hashes.reserve(authCreds.size());
357 for (auto const& o : authCreds)
358 hashes.emplace_back(sha512Half(o.first, o.second));
359
360 return {
361 ltDEPOSIT_PREAUTH,
363}
364
365//------------------------------------------------------------------------------
366
367Keylet
368unchecked(uint256 const& key) noexcept
369{
370 return {ltANY, key};
371}
372
373Keylet
374ownerDir(AccountID const& id) noexcept
375{
376 return {ltDIR_NODE, indexHash(LedgerNameSpace::OWNER_DIR, id)};
377}
378
379Keylet
380page(uint256 const& key, std::uint64_t index) noexcept
381{
382 if (index == 0)
383 return {ltDIR_NODE, key};
384
385 return {ltDIR_NODE, indexHash(LedgerNameSpace::DIR_NODE, key, index)};
386}
387
388Keylet
389escrow(AccountID const& src, std::uint32_t seq) noexcept
390{
391 return {ltESCROW, indexHash(LedgerNameSpace::ESCROW, src, seq)};
392}
393
394Keylet
395payChan(AccountID const& src, AccountID const& dst, std::uint32_t seq) noexcept
396{
397 return {
398 ltPAYCHAN,
400}
401
402Keylet
404{
406 std::memcpy(buf.data(), owner.data(), owner.size());
407 return {ltNFTOKEN_PAGE, uint256{buf}};
408}
409
410Keylet
412{
414 std::memcpy(id.data(), owner.data(), owner.size());
415 return {ltNFTOKEN_PAGE, id};
416}
417
418Keylet
419nftpage(Keylet const& k, uint256 const& token)
420{
421 XRPL_ASSERT(
422 k.type == ltNFTOKEN_PAGE, "ripple::keylet::nftpage : valid input type");
423 return {ltNFTOKEN_PAGE, (k.key & ~nft::pageMask) + (token & nft::pageMask)};
424}
425
426Keylet
428{
429 return {
430 ltNFTOKEN_OFFER, indexHash(LedgerNameSpace::NFTOKEN_OFFER, owner, seq)};
431}
432
433Keylet
434nft_buys(uint256 const& id) noexcept
435{
436 return {ltDIR_NODE, indexHash(LedgerNameSpace::NFTOKEN_BUY_OFFERS, id)};
437}
438
439Keylet
440nft_sells(uint256 const& id) noexcept
441{
442 return {ltDIR_NODE, indexHash(LedgerNameSpace::NFTOKEN_SELL_OFFERS, id)};
443}
444
445Keylet
446amm(Asset const& issue1, Asset const& issue2) noexcept
447{
448 auto const& [minI, maxI] =
449 std::minmax(issue1.get<Issue>(), issue2.get<Issue>());
450 return amm(indexHash(
452 minI.account,
453 minI.currency,
454 maxI.account,
455 maxI.currency));
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 {
468 ltDELEGATE,
469 indexHash(LedgerNameSpace::DELEGATE, account, authorizedAccount)};
470}
471
472Keylet
474{
475 // A door account can support multiple bridges. On the locking chain
476 // there can only be one bridge per lockingChainCurrency. On the issuing
477 // chain there can only be one bridge per issuingChainCurrency.
478 auto const& issue = bridge.issue(chainType);
479 return {
480 ltBRIDGE,
481 indexHash(
482 LedgerNameSpace::BRIDGE, bridge.door(chainType), issue.currency)};
483}
484
485Keylet
487{
488 return {
489 ltXCHAIN_OWNED_CLAIM_ID,
490 indexHash(
492 bridge.lockingChainDoor(),
493 bridge.lockingChainIssue(),
494 bridge.issuingChainDoor(),
495 bridge.issuingChainIssue(),
496 seq)};
497}
498
499Keylet
501{
502 return {
503 ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID,
504 indexHash(
506 bridge.lockingChainDoor(),
507 bridge.lockingChainIssue(),
508 bridge.issuingChainDoor(),
509 bridge.issuingChainIssue(),
510 seq)};
511}
512
513Keylet
514did(AccountID const& account) noexcept
515{
516 return {ltDID, indexHash(LedgerNameSpace::DID, account)};
517}
518
519Keylet
520oracle(AccountID const& account, std::uint32_t const& documentID) noexcept
521{
522 return {ltORACLE, indexHash(LedgerNameSpace::ORACLE, account, documentID)};
523}
524
525Keylet
526mptIssuance(std::uint32_t seq, AccountID const& issuer) noexcept
527{
528 return mptIssuance(makeMptID(seq, issuer));
529}
530
531Keylet
532mptIssuance(MPTID const& issuanceID) noexcept
533{
534 return {
535 ltMPTOKEN_ISSUANCE,
537}
538
539Keylet
540mptoken(MPTID const& issuanceID, AccountID const& holder) noexcept
541{
542 return mptoken(mptIssuance(issuanceID).key, holder);
543}
544
545Keylet
546mptoken(uint256 const& issuanceKey, AccountID const& holder) noexcept
547{
548 return {
549 ltMPTOKEN, indexHash(LedgerNameSpace::MPTOKEN, issuanceKey, holder)};
550}
551
552Keylet
554 AccountID const& subject,
555 AccountID const& issuer,
556 Slice const& credType) noexcept
557{
558 return {
559 ltCREDENTIAL,
560 indexHash(LedgerNameSpace::CREDENTIAL, subject, issuer, credType)};
561}
562
563Keylet
564vault(AccountID const& owner, std::uint32_t seq) noexcept
565{
566 return vault(indexHash(LedgerNameSpace::VAULT, owner, seq));
567}
568
569Keylet
570permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept
571{
572 return {
573 ltPERMISSIONED_DOMAIN,
575}
576
577Keylet
578permissionedDomain(uint256 const& domainID) noexcept
579{
580 return {ltPERMISSIONED_DOMAIN, domainID};
581}
582
583} // namespace keylet
584
585} // namespace ripple
Specifies an order book.
Definition Book.h:36
Issue in
Definition Book.h:38
Issue out
Definition Book.h:39
std::optional< uint256 > domain
Definition Book.h:40
A currency issued by an account.
Definition Issue.h:33
AccountID account
Definition Issue.h:36
Currency currency
Definition Issue.h:35
A type that represents either a sequence value or a ticket value.
Definition SeqProxy.h:56
constexpr std::uint32_t value() const
Definition SeqProxy.h:82
constexpr bool isTicket() const
Definition SeqProxy.h:94
An immutable linear range of bytes.
Definition Slice.h:46
static constexpr std::size_t size()
Definition base_uint.h:526
iterator end()
Definition base_uint.h:141
T emplace_back(T... args)
T memcpy(T... args)
T minmax(T... args)
Keylet quality(Keylet const &k, std::uint64_t q) noexcept
The initial directory page for a specific quality.
Definition Indexes.cpp:280
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Definition Indexes.cpp:540
Keylet oracle(AccountID const &account, std::uint32_t const &documentID) noexcept
Definition Indexes.cpp:520
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Definition Indexes.cpp:465
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Definition Indexes.cpp:190
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Definition Indexes.cpp:570
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Definition Indexes.cpp:230
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Definition Indexes.cpp:446
Keylet line(AccountID const &id0, AccountID const &id1, Currency const &currency) noexcept
The index of a trust line for a given currency.
Definition Indexes.cpp:244
Keylet const & amendments() noexcept
The index of the amendment table.
Definition Indexes.cpp:214
Keylet nftpage(Keylet const &k, uint256 const &token)
Definition Indexes.cpp:419
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:526
Keylet xChainClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Definition Indexes.cpp:486
Keylet did(AccountID const &account) noexcept
Definition Indexes.cpp:514
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:564
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
Definition Indexes.cpp:380
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Definition Indexes.cpp:368
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Definition Indexes.cpp:389
Keylet nftpage_min(AccountID const &owner)
NFT page keylets.
Definition Indexes.cpp:403
Keylet bridge(STXChainBridge const &bridge, STXChainBridge::ChainType chainType)
Definition Indexes.cpp:473
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Definition Indexes.cpp:222
Keylet nftpage_max(AccountID const &owner)
A keylet for the owner's last possible NFT page.
Definition Indexes.cpp:411
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:374
Keylet nft_buys(uint256 const &id) noexcept
The directory of buy offers for the specified NFT.
Definition Indexes.cpp:434
Keylet const & skip() noexcept
The index of the "short" skip list.
Definition Indexes.cpp:196
Keylet nft_sells(uint256 const &id) noexcept
The directory of sell offers for the specified NFT.
Definition Indexes.cpp:440
Keylet signers(AccountID const &account) noexcept
A SignerList.
Definition Indexes.cpp:330
Keylet xChainCreateAccountClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Definition Indexes.cpp:500
Keylet nftoffer(AccountID const &owner, std::uint32_t seq)
An offer from an account to buy or sell an NFT.
Definition Indexes.cpp:427
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Definition Indexes.cpp:336
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
Definition Indexes.cpp:274
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Definition Indexes.cpp:342
Keylet payChan(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Definition Indexes.cpp:395
uint256 constexpr pageMask(std::string_view("0000000000000000000000000000000000000000ffffffffffffffffffffffff"))
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
bool isConsistent(Book const &book)
Definition Book.cpp:29
LedgerNameSpace
Type-specific prefix for calculating ledger indices.
Definition Indexes.cpp:66
std::uint64_t getQuality(uint256 const &uBase)
Definition Indexes.cpp:149
base_uint< 256 > uint256
Definition base_uint.h:558
base_uint< 192 > MPTID
MPTID is a 192-bit value representing MPT Issuance ID, which is a concatenation of a 32-bit sequence ...
Definition UintTypes.h:64
static uint256 indexHash(LedgerNameSpace space, Args const &... args)
Definition Indexes.cpp:109
uint256 getQualityNext(uint256 const &uBase)
Definition Indexes.cpp:141
uint256 getTicketIndex(AccountID const &account, std::uint32_t uSequence)
Definition Indexes.cpp:156
@ ltCHILD
A special type, matching any ledger type except directory nodes.
@ ltANY
A special type, matching any ledger entry type.
@ credential
Credentials signature.
MPTID makeMptID(std::uint32_t sequence, AccountID const &account)
Definition Indexes.cpp:170
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition digest.h:224
uint256 getBookBase(Book const &book)
Definition Indexes.cpp:115
T reserve(T... args)
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:39
LedgerEntryType type
Definition Keylet.h:41
uint256 key
Definition Keylet.h:40
Keylet operator()(Book const &b) const
Definition Indexes.cpp:238
Keylet operator()(Keylet const &k) const
Definition Indexes.cpp:299
Keylet operator()(AccountID const &id, std::uint32_t ticketSeq) const
Definition Indexes.cpp:308