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