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