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