rippled
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 <ripple/protocol/Indexes.h>
21 #include <ripple/protocol/SeqProxy.h>
22 #include <ripple/protocol/digest.h>
23 #include <ripple/protocol/nftPageMask.h>
24 #include <algorithm>
25 #include <cassert>
26 
27 namespace ripple {
28 
47  ACCOUNT = 'a',
48  DIR_NODE = 'd',
49  TRUST_LINE = 'r',
50  OFFER = 'o',
51  OWNER_DIR = 'O',
52  BOOK_DIR = 'B',
53  SKIP_LIST = 's',
54  ESCROW = 'u',
55  AMENDMENTS = 'f',
56  FEE_SETTINGS = 'e',
57  TICKET = 'T',
58  SIGNER_LIST = 'S',
59  XRP_PAYMENT_CHANNEL = 'x',
60  CHECK = 'C',
61  DEPOSIT_PREAUTH = 'p',
62  NEGATIVE_UNL = 'N',
63  NFTOKEN_OFFER = 'q',
64  NFTOKEN_BUY_OFFERS = 'h',
65  NFTOKEN_SELL_OFFERS = 'i',
66  AMM = 'A',
67 
68  // No longer used or supported. Left here to reserve the space
69  // to avoid accidental reuse.
70  CONTRACT [[deprecated]] = 'c',
71  GENERATOR [[deprecated]] = 'g',
72  NICKNAME [[deprecated]] = 'n',
73 };
74 
75 template <class... Args>
76 static uint256
77 indexHash(LedgerNameSpace space, Args const&... args)
78 {
79  return sha512Half(safe_cast<std::uint16_t>(space), args...);
80 }
81 
82 uint256
83 getBookBase(Book const& book)
84 {
85  assert(isConsistent(book));
86 
87  auto const index = indexHash(
89  book.in.currency,
90  book.out.currency,
91  book.in.account,
92  book.out.account);
93 
94  // Return with quality 0.
95  auto k = keylet::quality({ltDIR_NODE, index}, 0);
96 
97  return k.key;
98 }
99 
100 uint256
101 getQualityNext(uint256 const& uBase)
102 {
103  static constexpr uint256 nextq(
104  "0000000000000000000000000000000000000000000000010000000000000000");
105  return uBase + nextq;
106 }
107 
109 getQuality(uint256 const& uBase)
110 {
111  // VFALCO [base_uint] This assumes a certain storage format
112  return boost::endian::big_to_native(((std::uint64_t*)uBase.end())[-1]);
113 }
114 
115 uint256
116 getTicketIndex(AccountID const& account, std::uint32_t ticketSeq)
117 {
118  return indexHash(
119  LedgerNameSpace::TICKET, account, std::uint32_t(ticketSeq));
120 }
121 
122 uint256
123 getTicketIndex(AccountID const& account, SeqProxy ticketSeq)
124 {
125  assert(ticketSeq.isTicket());
126  return getTicketIndex(account, ticketSeq.value());
127 }
128 
129 //------------------------------------------------------------------------------
130 
131 namespace keylet {
132 
133 Keylet
134 account(AccountID const& id) noexcept
135 {
137 }
138 
139 Keylet
140 child(uint256 const& key) noexcept
141 {
142  return {ltCHILD, key};
143 }
144 
145 Keylet const&
146 skip() noexcept
147 {
148  static Keylet const ret{
150  return ret;
151 }
152 
153 Keylet
154 skip(LedgerIndex ledger) noexcept
155 {
156  return {
158  indexHash(
160  std::uint32_t(static_cast<std::uint32_t>(ledger) >> 16))};
161 }
162 
163 Keylet const&
164 amendments() noexcept
165 {
166  static Keylet const ret{
168  return ret;
169 }
170 
171 Keylet const&
172 fees() noexcept
173 {
174  static Keylet const ret{
176  return ret;
177 }
178 
179 Keylet const&
180 negativeUNL() noexcept
181 {
182  static Keylet const ret{
184  return ret;
185 }
186 
187 Keylet
188 book_t::operator()(Book const& b) const
189 {
190  return {ltDIR_NODE, getBookBase(b)};
191 }
192 
193 Keylet
195  AccountID const& id0,
196  AccountID const& id1,
197  Currency const& currency) noexcept
198 {
199  // There is code in SetTrust that calls us with id0 == id1, to allow users
200  // to locate and delete such "weird" trustlines. If we remove that code, we
201  // could enable this assert:
202  // assert(id0 != id1);
203 
204  // A trust line is shared between two accounts; while we typically think
205  // of this as an "issuer" and a "holder" the relationship is actually fully
206  // bidirectional.
207  //
208  // So that we can generate a unique ID for a trust line, regardess of which
209  // side of the line we're looking at, we define a "canonical" order for the
210  // two accounts (smallest then largest) and hash them in that order:
211  auto const accounts = std::minmax(id0, id1);
212 
213  return {
215  indexHash(
217  accounts.first,
218  accounts.second,
219  currency)};
220 }
221 
222 Keylet
223 offer(AccountID const& id, std::uint32_t seq) noexcept
224 {
225  return {ltOFFER, indexHash(LedgerNameSpace::OFFER, id, seq)};
226 }
227 
228 Keylet
229 quality(Keylet const& k, std::uint64_t q) noexcept
230 {
231  assert(k.type == ltDIR_NODE);
232 
233  // Indexes are stored in big endian format: they print as hex as stored.
234  // Most significant bytes are first and the least significant bytes
235  // represent adjacent entries. We place the quality, in big endian format,
236  // in the 8 right most bytes; this way, incrementing goes to the next entry
237  // for indexes.
238  uint256 x = k.key;
239 
240  // FIXME This is ugly and we can and should do better...
241  ((std::uint64_t*)x.end())[-1] = boost::endian::native_to_big(q);
242 
243  return {ltDIR_NODE, x};
244 }
245 
246 Keylet
247 next_t::operator()(Keylet const& k) const
248 {
249  assert(k.type == ltDIR_NODE);
250  return {ltDIR_NODE, getQualityNext(k.key)};
251 }
252 
253 Keylet
254 ticket_t::operator()(AccountID const& id, std::uint32_t ticketSeq) const
255 {
256  return {ltTICKET, getTicketIndex(id, ticketSeq)};
257 }
258 
259 Keylet
260 ticket_t::operator()(AccountID const& id, SeqProxy ticketSeq) const
261 {
262  return {ltTICKET, getTicketIndex(id, ticketSeq)};
263 }
264 
265 // This function is presently static, since it's never accessed from anywhere
266 // else. If we ever support multiple pages of signer lists, this would be the
267 // keylet used to locate them.
268 static Keylet
270 {
271  return {
273 }
274 
275 Keylet
276 signers(AccountID const& account) noexcept
277 {
278  return signers(account, 0);
279 }
280 
281 Keylet
282 check(AccountID const& id, std::uint32_t seq) noexcept
283 {
284  return {ltCHECK, indexHash(LedgerNameSpace::CHECK, id, seq)};
285 }
286 
287 Keylet
288 depositPreauth(AccountID const& owner, AccountID const& preauthorized) noexcept
289 {
290  return {
292  indexHash(LedgerNameSpace::DEPOSIT_PREAUTH, owner, preauthorized)};
293 }
294 
295 //------------------------------------------------------------------------------
296 
297 Keylet
298 unchecked(uint256 const& key) noexcept
299 {
300  return {ltANY, key};
301 }
302 
303 Keylet
304 ownerDir(AccountID const& id) noexcept
305 {
307 }
308 
309 Keylet
310 page(uint256 const& key, std::uint64_t index) noexcept
311 {
312  if (index == 0)
313  return {ltDIR_NODE, key};
314 
315  return {ltDIR_NODE, indexHash(LedgerNameSpace::DIR_NODE, key, index)};
316 }
317 
318 Keylet
319 escrow(AccountID const& src, std::uint32_t seq) noexcept
320 {
321  return {ltESCROW, indexHash(LedgerNameSpace::ESCROW, src, seq)};
322 }
323 
324 Keylet
325 payChan(AccountID const& src, AccountID const& dst, std::uint32_t seq) noexcept
326 {
327  return {
328  ltPAYCHAN,
330 }
331 
332 Keylet
333 nftpage_min(AccountID const& owner)
334 {
336  std::memcpy(buf.data(), owner.data(), owner.size());
337  return {ltNFTOKEN_PAGE, uint256{buf}};
338 }
339 
340 Keylet
341 nftpage_max(AccountID const& owner)
342 {
343  uint256 id = nft::pageMask;
344  std::memcpy(id.data(), owner.data(), owner.size());
345  return {ltNFTOKEN_PAGE, id};
346 }
347 
348 Keylet
349 nftpage(Keylet const& k, uint256 const& token)
350 {
351  assert(k.type == ltNFTOKEN_PAGE);
352  return {ltNFTOKEN_PAGE, (k.key & ~nft::pageMask) + (token & nft::pageMask)};
353 }
354 
355 Keylet
356 nftoffer(AccountID const& owner, std::uint32_t seq)
357 {
358  return {
360 }
361 
362 Keylet
363 nft_buys(uint256 const& id) noexcept
364 {
366 }
367 
368 Keylet
369 nft_sells(uint256 const& id) noexcept
370 {
372 }
373 
374 Keylet
375 amm(Issue const& issue1, Issue const& issue2) noexcept
376 {
377  auto const& [minI, maxI] = std::minmax(issue1, issue2);
378  return amm(indexHash(
380  minI.account,
381  minI.currency,
382  maxI.account,
383  maxI.currency));
384 }
385 
386 Keylet
387 amm(uint256 const& id) noexcept
388 {
389  return {ltAMM, id};
390 }
391 
392 } // namespace keylet
393 
394 } // namespace ripple
ripple::keylet::ownerDir
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition: Indexes.cpp:304
ripple::LedgerNameSpace::DIR_NODE
@ DIR_NODE
ripple::LedgerNameSpace::NFTOKEN_OFFER
@ NFTOKEN_OFFER
ripple::ltTICKET
@ ltTICKET
A ledger object which describes a ticket.
Definition: LedgerFormats.h:80
ripple::LedgerNameSpace::NICKNAME
@ NICKNAME
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::Issue
A currency issued by an account.
Definition: Issue.h:35
ripple::LedgerNameSpace::OFFER
@ OFFER
ripple::LedgerNameSpace::NFTOKEN_SELL_OFFERS
@ NFTOKEN_SELL_OFFERS
ripple::keylet::amendments
Keylet const & amendments() noexcept
The index of the amendment table.
Definition: Indexes.cpp:164
ripple::ltANY
@ ltANY
A special type, matching any ledger entry type.
Definition: LedgerFormats.h:182
ripple::LedgerNameSpace::GENERATOR
@ GENERATOR
ripple::isConsistent
bool isConsistent(Book const &book)
Definition: Book.cpp:25
ripple::LedgerNameSpace::AMENDMENTS
@ AMENDMENTS
ripple::Book::out
Issue out
Definition: Book.h:37
ripple::ltLEDGER_HASHES
@ ltLEDGER_HASHES
A ledger object that contains a list of ledger hashes.
Definition: LedgerFormats.h:102
ripple::LedgerNameSpace::NFTOKEN_BUY_OFFERS
@ NFTOKEN_BUY_OFFERS
ripple::getBookBase
uint256 getBookBase(Book const &book)
Definition: Indexes.cpp:83
ripple::LedgerNameSpace::CHECK
@ CHECK
ripple::keylet::amm
Keylet amm(Issue const &issue1, Issue const &issue2) noexcept
AMM entry.
Definition: Indexes.cpp:375
ripple::base_uint::end
iterator end()
Definition: base_uint.h:138
ripple::ltSIGNER_LIST
@ ltSIGNER_LIST
A ledger object which contains a signer list for an account.
Definition: LedgerFormats.h:86
ripple::keylet::nftoffer
Keylet nftoffer(AccountID const &owner, std::uint32_t seq)
An offer from an account to buy or sell an NFT.
Definition: Indexes.cpp:356
ripple::keylet::offer
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
Definition: Indexes.cpp:223
ripple::Issue::currency
Currency currency
Definition: Issue.h:38
ripple::keylet::skip
Keylet const & skip() noexcept
The index of the "short" skip list.
Definition: Indexes.cpp:146
ripple::keylet::child
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Definition: Indexes.cpp:140
ripple::LedgerNameSpace::SIGNER_LIST
@ SIGNER_LIST
ripple::ltCHECK
@ ltCHECK
A ledger object which describes a check.
Definition: LedgerFormats.h:136
ripple::getQualityNext
uint256 getQualityNext(uint256 const &uBase)
Definition: Indexes.cpp:101
ripple::ltFEE_SETTINGS
@ ltFEE_SETTINGS
The ledger object which lists the network's fee settings.
Definition: LedgerFormats.h:118
ripple::LedgerNameSpace
LedgerNameSpace
Type-specific prefix for calculating ledger indices.
Definition: Indexes.cpp:46
ripple::LedgerNameSpace::SKIP_LIST
@ SKIP_LIST
ripple::ltCHILD
@ ltCHILD
A special type, matching any ledger type except directory nodes.
Definition: LedgerFormats.h:195
ripple::base_uint::data
pointer data()
Definition: base_uint.h:122
algorithm
ripple::getTicketIndex
uint256 getTicketIndex(AccountID const &account, std::uint32_t ticketSeq)
Definition: Indexes.cpp:116
ripple::keylet::next_t::operator()
Keylet operator()(Keylet const &k) const
Definition: Indexes.cpp:247
ripple::base_uint::size
constexpr static std::size_t size()
Definition: base_uint.h:519
ripple::ltDIR_NODE
@ ltDIR_NODE
A ledger object which contains a list of object identifiers.
Definition: LedgerFormats.h:66
ripple::nft::pageMask
constexpr uint256 pageMask(std::string_view("0000000000000000000000000000000000000000ffffffffffffffffffffffff"))
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:550
ripple::SeqProxy::isTicket
constexpr bool isTicket() const
Definition: SeqProxy.h:94
ripple::Keylet::key
uint256 key
Definition: Keylet.h:40
ripple::base_uint< 256 >
ripple::ltAMENDMENTS
@ ltAMENDMENTS
The ledger object which lists details about amendments on the network.
Definition: LedgerFormats.h:110
ripple::indexHash
static uint256 indexHash(LedgerNameSpace space, Args const &... args)
Definition: Indexes.cpp:77
ripple::keylet::escrow
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Definition: Indexes.cpp:319
ripple::keylet::nftpage_min
Keylet nftpage_min(AccountID const &owner)
NFT page keylets.
Definition: Indexes.cpp:333
ripple::ltOFFER
@ ltOFFER
A ledger object which describes an offer on the DEX.
Definition: LedgerFormats.h:92
ripple::keylet::nftpage
Keylet nftpage(Keylet const &k, uint256 const &token)
Definition: Indexes.cpp:349
ripple::LedgerNameSpace::NEGATIVE_UNL
@ NEGATIVE_UNL
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:134
ripple::ltESCROW
@ ltESCROW
A ledger object describing a single escrow.
Definition: LedgerFormats.h:124
std::minmax
T minmax(T... args)
ripple::LedgerNameSpace::DEPOSIT_PREAUTH
@ DEPOSIT_PREAUTH
ripple::ltNFTOKEN_OFFER
@ ltNFTOKEN_OFFER
A ledger object which identifies an offer to buy or sell an NFT.
Definition: LedgerFormats.h:162
ripple::keylet::page
Keylet page(uint256 const &key, std::uint64_t index) noexcept
A page in a directory.
Definition: Indexes.cpp:310
ripple::LedgerNameSpace::CONTRACT
@ CONTRACT
ripple::LedgerNameSpace::OWNER_DIR
@ OWNER_DIR
std::array< std::uint8_t, 32 >
ripple::Keylet::type
LedgerEntryType type
Definition: Keylet.h:41
ripple::ltDEPOSIT_PREAUTH
@ ltDEPOSIT_PREAUTH
A ledger object which describes a deposit preauthorization.
Definition: LedgerFormats.h:142
ripple::keylet::nft_sells
Keylet nft_sells(uint256 const &id) noexcept
The directory of sell offers for the specified NFT.
Definition: Indexes.cpp:369
ripple::keylet::nftpage_max
Keylet nftpage_max(AccountID const &owner)
A keylet for the owner's last possible NFT page.
Definition: Indexes.cpp:341
ripple::keylet::ticket_t::operator()
Keylet operator()(AccountID const &id, std::uint32_t ticketSeq) const
Definition: Indexes.cpp:254
ripple::LedgerNameSpace::TRUST_LINE
@ TRUST_LINE
std::uint16_t
ripple::keylet::nft_buys
Keylet nft_buys(uint256 const &id) noexcept
The directory of buy offers for the specified NFT.
Definition: Indexes.cpp:363
ripple::keylet::line
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:194
ripple::LedgerNameSpace::FEE_SETTINGS
@ FEE_SETTINGS
ripple::keylet::unchecked
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Definition: Indexes.cpp:298
ripple::LedgerNameSpace::AMM
@ AMM
ripple::SeqProxy::value
constexpr std::uint32_t value() const
Definition: SeqProxy.h:82
ripple::ltNFTOKEN_PAGE
@ ltNFTOKEN_PAGE
A ledger object which contains a list of NFTs.
Definition: LedgerFormats.h:156
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::keylet::book_t::operator()
Keylet operator()(Book const &b) const
Definition: Indexes.cpp:188
ripple::ltNEGATIVE_UNL
@ ltNEGATIVE_UNL
The ledger object which tracks the current negative UNL state.
Definition: LedgerFormats.h:150
ripple::keylet::payChan
Keylet payChan(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Definition: Indexes.cpp:325
ripple::ltACCOUNT_ROOT
@ ltACCOUNT_ROOT
A ledger object which describes an account.
Definition: LedgerFormats.h:59
ripple::sha512Half
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:216
cassert
ripple::SeqProxy
A type that represents either a sequence value or a ticket value.
Definition: SeqProxy.h:55
ripple::LedgerNameSpace::XRP_PAYMENT_CHANNEL
@ XRP_PAYMENT_CHANNEL
ripple::LedgerNameSpace::TICKET
@ TICKET
ripple::keylet::fees
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Definition: Indexes.cpp:172
std::memcpy
T memcpy(T... args)
ripple::LedgerNameSpace::ESCROW
@ ESCROW
ripple::Book
Specifies an order book.
Definition: Book.h:33
ripple::ltRIPPLE_STATE
@ ltRIPPLE_STATE
A ledger object which describes a bidirectional trust line.
Definition: LedgerFormats.h:74
ripple::keylet::quality
Keylet quality(Keylet const &k, std::uint64_t q) noexcept
The initial directory page for a specific quality.
Definition: Indexes.cpp:229
ripple::LedgerNameSpace::ACCOUNT
@ ACCOUNT
ripple::LedgerNameSpace::BOOK_DIR
@ BOOK_DIR
ripple::keylet::signers
static Keylet signers(AccountID const &account, std::uint32_t page) noexcept
Definition: Indexes.cpp:269
ripple::keylet::negativeUNL
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Definition: Indexes.cpp:180
ripple::keylet::check
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Definition: Indexes.cpp:282
ripple::keylet::depositPreauth
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Definition: Indexes.cpp:288
ripple::getQuality
std::uint64_t getQuality(uint256 const &uBase)
Definition: Indexes.cpp:109
ripple::ltAMM
@ ltAMM
The ledger object which tracks the AMM.
Definition: LedgerFormats.h:168
ripple::Book::in
Issue in
Definition: Book.h:36
ripple::Issue::account
AccountID account
Definition: Issue.h:39
ripple::ltPAYCHAN
@ ltPAYCHAN
A ledger object describing a single unidirectional XRP payment channel.
Definition: LedgerFormats.h:130