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