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 = indexHash(
122 book.in.currency,
123 book.out.currency,
124 book.in.account,
125 book.out.account);
126
127 // Return with quality 0.
128 auto k = keylet::quality({ltDIR_NODE, index}, 0);
129
130 return k.key;
131}
132
135{
136 static constexpr uint256 nextq(
137 "0000000000000000000000000000000000000000000000010000000000000000");
138 return uBase + nextq;
139}
140
142getQuality(uint256 const& uBase)
143{
144 // VFALCO [base_uint] This assumes a certain storage format
145 return boost::endian::big_to_native(((std::uint64_t*)uBase.end())[-1]);
146}
147
149getTicketIndex(AccountID const& account, std::uint32_t ticketSeq)
150{
151 return indexHash(
152 LedgerNameSpace::TICKET, account, std::uint32_t(ticketSeq));
153}
154
156getTicketIndex(AccountID const& account, SeqProxy ticketSeq)
157{
158 XRPL_ASSERT(ticketSeq.isTicket(), "ripple::getTicketIndex : valid input");
159 return getTicketIndex(account, ticketSeq.value());
160}
161
162MPTID
163makeMptID(std::uint32_t sequence, AccountID const& account)
164{
165 MPTID u;
166 sequence = boost::endian::native_to_big(sequence);
167 memcpy(u.data(), &sequence, sizeof(sequence));
168 memcpy(u.data() + sizeof(sequence), account.data(), sizeof(account));
169 return u;
170}
171
172//------------------------------------------------------------------------------
173
174namespace keylet {
175
176Keylet
177account(AccountID const& id) noexcept
178{
179 return Keylet{ltACCOUNT_ROOT, indexHash(LedgerNameSpace::ACCOUNT, id)};
180}
181
182Keylet
183child(uint256 const& key) noexcept
184{
185 return {ltCHILD, key};
186}
187
188Keylet const&
189skip() noexcept
190{
191 static Keylet const ret{
192 ltLEDGER_HASHES, indexHash(LedgerNameSpace::SKIP_LIST)};
193 return ret;
194}
195
196Keylet
197skip(LedgerIndex ledger) noexcept
198{
199 return {
200 ltLEDGER_HASHES,
201 indexHash(
203 std::uint32_t(static_cast<std::uint32_t>(ledger) >> 16))};
204}
205
206Keylet const&
207amendments() noexcept
208{
209 static Keylet const ret{
211 return ret;
212}
213
214Keylet const&
215fees() noexcept
216{
217 static Keylet const ret{
219 return ret;
220}
221
222Keylet const&
223negativeUNL() noexcept
224{
225 static Keylet const ret{
227 return ret;
228}
229
230Keylet
232{
233 return {ltDIR_NODE, getBookBase(b)};
234}
235
236Keylet
238 AccountID const& id0,
239 AccountID const& id1,
240 Currency const& currency) noexcept
241{
242 // There is code in SetTrust that calls us with id0 == id1, to allow users
243 // to locate and delete such "weird" trustlines. If we remove that code, we
244 // could enable this assert:
245 // XRPL_ASSERT(id0 != id1, "ripple::keylet::line : accounts must be
246 // different");
247
248 // A trust line is shared between two accounts; while we typically think
249 // of this as an "issuer" and a "holder" the relationship is actually fully
250 // bidirectional.
251 //
252 // So that we can generate a unique ID for a trust line, regardess of which
253 // side of the line we're looking at, we define a "canonical" order for the
254 // two accounts (smallest then largest) and hash them in that order:
255 auto const accounts = std::minmax(id0, id1);
256
257 return {
258 ltRIPPLE_STATE,
259 indexHash(
261 accounts.first,
262 accounts.second,
263 currency)};
264}
265
266Keylet
267offer(AccountID const& id, std::uint32_t seq) noexcept
268{
269 return {ltOFFER, indexHash(LedgerNameSpace::OFFER, id, seq)};
270}
271
272Keylet
273quality(Keylet const& k, std::uint64_t q) noexcept
274{
275 XRPL_ASSERT(
276 k.type == ltDIR_NODE, "ripple::keylet::quality : valid input type");
277
278 // Indexes are stored in big endian format: they print as hex as stored.
279 // Most significant bytes are first and the least significant bytes
280 // represent adjacent entries. We place the quality, in big endian format,
281 // in the 8 right most bytes; this way, incrementing goes to the next entry
282 // for indexes.
283 uint256 x = k.key;
284
285 // FIXME This is ugly and we can and should do better...
286 ((std::uint64_t*)x.end())[-1] = boost::endian::native_to_big(q);
287
288 return {ltDIR_NODE, x};
289}
290
291Keylet
293{
294 XRPL_ASSERT(
295 k.type == ltDIR_NODE,
296 "ripple::keylet::next_t::operator() : valid input type");
297 return {ltDIR_NODE, getQualityNext(k.key)};
298}
299
300Keylet
302{
303 return {ltTICKET, getTicketIndex(id, ticketSeq)};
304}
305
306Keylet
307ticket_t::operator()(AccountID const& id, SeqProxy ticketSeq) const
308{
309 return {ltTICKET, getTicketIndex(id, ticketSeq)};
310}
311
312// This function is presently static, since it's never accessed from anywhere
313// else. If we ever support multiple pages of signer lists, this would be the
314// keylet used to locate them.
315static Keylet
316signers(AccountID const& account, std::uint32_t page) noexcept
317{
318 return {
319 ltSIGNER_LIST, indexHash(LedgerNameSpace::SIGNER_LIST, account, page)};
320}
321
322Keylet
323signers(AccountID const& account) noexcept
324{
325 return signers(account, 0);
326}
327
328Keylet
329check(AccountID const& id, std::uint32_t seq) noexcept
330{
331 return {ltCHECK, indexHash(LedgerNameSpace::CHECK, id, seq)};
332}
333
334Keylet
335depositPreauth(AccountID const& owner, AccountID const& preauthorized) noexcept
336{
337 return {
338 ltDEPOSIT_PREAUTH,
339 indexHash(LedgerNameSpace::DEPOSIT_PREAUTH, owner, preauthorized)};
340}
341
342// Credentials should be sorted here, use credentials::makeSorted
343Keylet
345 AccountID const& owner,
346 std::set<std::pair<AccountID, Slice>> const& authCreds) noexcept
347{
349 hashes.reserve(authCreds.size());
350 for (auto const& o : authCreds)
351 hashes.emplace_back(sha512Half(o.first, o.second));
352
353 return {
354 ltDEPOSIT_PREAUTH,
356}
357
358//------------------------------------------------------------------------------
359
360Keylet
361unchecked(uint256 const& key) noexcept
362{
363 return {ltANY, key};
364}
365
366Keylet
367ownerDir(AccountID const& id) noexcept
368{
369 return {ltDIR_NODE, indexHash(LedgerNameSpace::OWNER_DIR, id)};
370}
371
372Keylet
373page(uint256 const& key, std::uint64_t index) noexcept
374{
375 if (index == 0)
376 return {ltDIR_NODE, key};
377
378 return {ltDIR_NODE, indexHash(LedgerNameSpace::DIR_NODE, key, index)};
379}
380
381Keylet
382escrow(AccountID const& src, std::uint32_t seq) noexcept
383{
384 return {ltESCROW, indexHash(LedgerNameSpace::ESCROW, src, seq)};
385}
386
387Keylet
388payChan(AccountID const& src, AccountID const& dst, std::uint32_t seq) noexcept
389{
390 return {
391 ltPAYCHAN,
393}
394
395Keylet
397{
399 std::memcpy(buf.data(), owner.data(), owner.size());
400 return {ltNFTOKEN_PAGE, uint256{buf}};
401}
402
403Keylet
405{
407 std::memcpy(id.data(), owner.data(), owner.size());
408 return {ltNFTOKEN_PAGE, id};
409}
410
411Keylet
412nftpage(Keylet const& k, uint256 const& token)
413{
414 XRPL_ASSERT(
415 k.type == ltNFTOKEN_PAGE, "ripple::keylet::nftpage : valid input type");
416 return {ltNFTOKEN_PAGE, (k.key & ~nft::pageMask) + (token & nft::pageMask)};
417}
418
419Keylet
421{
422 return {
423 ltNFTOKEN_OFFER, indexHash(LedgerNameSpace::NFTOKEN_OFFER, owner, seq)};
424}
425
426Keylet
427nft_buys(uint256 const& id) noexcept
428{
429 return {ltDIR_NODE, indexHash(LedgerNameSpace::NFTOKEN_BUY_OFFERS, id)};
430}
431
432Keylet
433nft_sells(uint256 const& id) noexcept
434{
435 return {ltDIR_NODE, indexHash(LedgerNameSpace::NFTOKEN_SELL_OFFERS, id)};
436}
437
438Keylet
439amm(Asset const& issue1, Asset const& issue2) noexcept
440{
441 auto const& [minI, maxI] =
442 std::minmax(issue1.get<Issue>(), issue2.get<Issue>());
443 return amm(indexHash(
445 minI.account,
446 minI.currency,
447 maxI.account,
448 maxI.currency));
449}
450
451Keylet
452amm(uint256 const& id) noexcept
453{
454 return {ltAMM, id};
455}
456
457Keylet
458delegate(AccountID const& account, AccountID const& authorizedAccount) noexcept
459{
460 return {
461 ltDELEGATE,
462 indexHash(LedgerNameSpace::DELEGATE, account, authorizedAccount)};
463}
464
465Keylet
467{
468 // A door account can support multiple bridges. On the locking chain
469 // there can only be one bridge per lockingChainCurrency. On the issuing
470 // chain there can only be one bridge per issuingChainCurrency.
471 auto const& issue = bridge.issue(chainType);
472 return {
473 ltBRIDGE,
474 indexHash(
475 LedgerNameSpace::BRIDGE, bridge.door(chainType), issue.currency)};
476}
477
478Keylet
480{
481 return {
482 ltXCHAIN_OWNED_CLAIM_ID,
483 indexHash(
485 bridge.lockingChainDoor(),
486 bridge.lockingChainIssue(),
487 bridge.issuingChainDoor(),
488 bridge.issuingChainIssue(),
489 seq)};
490}
491
492Keylet
494{
495 return {
496 ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID,
497 indexHash(
499 bridge.lockingChainDoor(),
500 bridge.lockingChainIssue(),
501 bridge.issuingChainDoor(),
502 bridge.issuingChainIssue(),
503 seq)};
504}
505
506Keylet
507did(AccountID const& account) noexcept
508{
509 return {ltDID, indexHash(LedgerNameSpace::DID, account)};
510}
511
512Keylet
513oracle(AccountID const& account, std::uint32_t const& documentID) noexcept
514{
515 return {ltORACLE, indexHash(LedgerNameSpace::ORACLE, account, documentID)};
516}
517
518Keylet
519mptIssuance(std::uint32_t seq, AccountID const& issuer) noexcept
520{
521 return mptIssuance(makeMptID(seq, issuer));
522}
523
524Keylet
525mptIssuance(MPTID const& issuanceID) noexcept
526{
527 return {
528 ltMPTOKEN_ISSUANCE,
530}
531
532Keylet
533mptoken(MPTID const& issuanceID, AccountID const& holder) noexcept
534{
535 return mptoken(mptIssuance(issuanceID).key, holder);
536}
537
538Keylet
539mptoken(uint256 const& issuanceKey, AccountID const& holder) noexcept
540{
541 return {
542 ltMPTOKEN, indexHash(LedgerNameSpace::MPTOKEN, issuanceKey, holder)};
543}
544
545Keylet
547 AccountID const& subject,
548 AccountID const& issuer,
549 Slice const& credType) noexcept
550{
551 return {
552 ltCREDENTIAL,
553 indexHash(LedgerNameSpace::CREDENTIAL, subject, issuer, credType)};
554}
555
556Keylet
557vault(AccountID const& owner, std::uint32_t seq) noexcept
558{
559 return vault(indexHash(LedgerNameSpace::VAULT, owner, seq));
560}
561
562Keylet
564{
565 return {
566 ltPERMISSIONED_DOMAIN,
568}
569
570Keylet
571permissionedDomain(uint256 const& domainID) noexcept
572{
573 return {ltPERMISSIONED_DOMAIN, domainID};
574}
575
576} // namespace keylet
577
578} // namespace ripple
Specifies an order book.
Definition: Book.h:35
Issue in
Definition: Book.h:37
Issue out
Definition: Book.h:38
A currency issued by an account.
Definition: Issue.h:36
AccountID account
Definition: Issue.h:39
Currency currency
Definition: Issue.h:38
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
pointer data()
Definition: base_uint.h:125
static constexpr std::size_t size()
Definition: base_uint.h:526
iterator end()
Definition: base_uint.h:141
Convenience class to test AMM functionality.
Definition: AMM.h:124
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:273
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Definition: Indexes.cpp:533
Keylet oracle(AccountID const &account, std::uint32_t const &documentID) noexcept
Definition: Indexes.cpp:513
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Definition: Indexes.cpp:458
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Definition: Indexes.cpp:183
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Definition: Indexes.cpp:563
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Definition: Indexes.cpp:223
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Definition: Indexes.cpp:439
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:237
Keylet const & amendments() noexcept
The index of the amendment table.
Definition: Indexes.cpp:207
Keylet nftpage(Keylet const &k, uint256 const &token)
Definition: Indexes.cpp:412
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition: Indexes.cpp:519
Keylet xChainClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Definition: Indexes.cpp:479
Keylet did(AccountID const &account) noexcept
Definition: Indexes.cpp:507
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Definition: Indexes.cpp:557
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
Definition: Indexes.cpp:373
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Definition: Indexes.cpp:361
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Definition: Indexes.cpp:382
Keylet nftpage_min(AccountID const &owner)
NFT page keylets.
Definition: Indexes.cpp:396
Keylet bridge(STXChainBridge const &bridge, STXChainBridge::ChainType chainType)
Definition: Indexes.cpp:466
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Definition: Indexes.cpp:215
Keylet nftpage_max(AccountID const &owner)
A keylet for the owner's last possible NFT page.
Definition: Indexes.cpp:404
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition: Indexes.cpp:367
Keylet nft_buys(uint256 const &id) noexcept
The directory of buy offers for the specified NFT.
Definition: Indexes.cpp:427
Keylet const & skip() noexcept
The index of the "short" skip list.
Definition: Indexes.cpp:189
Keylet nft_sells(uint256 const &id) noexcept
The directory of sell offers for the specified NFT.
Definition: Indexes.cpp:433
Keylet signers(AccountID const &account) noexcept
A SignerList.
Definition: Indexes.cpp:323
Keylet xChainCreateAccountClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Definition: Indexes.cpp:493
Keylet nftoffer(AccountID const &owner, std::uint32_t seq)
An offer from an account to buy or sell an NFT.
Definition: Indexes.cpp:420
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
Definition: Indexes.cpp:267
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Definition: Indexes.cpp:335
Keylet payChan(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Definition: Indexes.cpp:388
uint256 constexpr pageMask(std::string_view("0000000000000000000000000000000000000000ffffffffffffffffffffffff"))
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
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:142
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:134
uint256 getTicketIndex(AccountID const &account, std::uint32_t uSequence)
Definition: Indexes.cpp:149
@ ltCHILD
A special type, matching any ledger type except directory nodes.
Definition: LedgerFormats.h:91
@ ltANY
A special type, matching any ledger entry type.
Definition: LedgerFormats.h:78
@ credential
Credentials signature.
MPTID makeMptID(std::uint32_t sequence, AccountID const &account)
Definition: Indexes.cpp:163
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:225
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:231
Keylet operator()(Keylet const &k) const
Definition: Indexes.cpp:292
Keylet operator()(AccountID const &id, std::uint32_t ticketSeq) const
Definition: Indexes.cpp:301
Set the sequence number on a JTx.
Definition: seq.h:34