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 
67  // No longer used or supported. Left here to reserve the space
68  // to avoid accidental reuse.
69  CONTRACT [[deprecated]] = 'c',
70  GENERATOR [[deprecated]] = 'g',
71  NICKNAME [[deprecated]] = 'n',
72 };
73 
74 template <class... Args>
75 static uint256
76 indexHash(LedgerNameSpace space, Args const&... args)
77 {
78  return sha512Half(safe_cast<std::uint16_t>(space), args...);
79 }
80 
81 uint256
82 getBookBase(Book const& book)
83 {
84  assert(isConsistent(book));
85 
86  auto const index = indexHash(
88  book.in.currency,
89  book.out.currency,
90  book.in.account,
91  book.out.account);
92 
93  // Return with quality 0.
94  auto k = keylet::quality({ltDIR_NODE, index}, 0);
95 
96  return k.key;
97 }
98 
99 uint256
100 getQualityNext(uint256 const& uBase)
101 {
102  static constexpr uint256 nextq(
103  "0000000000000000000000000000000000000000000000010000000000000000");
104  return uBase + nextq;
105 }
106 
108 getQuality(uint256 const& uBase)
109 {
110  // VFALCO [base_uint] This assumes a certain storage format
111  return boost::endian::big_to_native(((std::uint64_t*)uBase.end())[-1]);
112 }
113 
114 uint256
115 getTicketIndex(AccountID const& account, std::uint32_t ticketSeq)
116 {
117  return indexHash(
118  LedgerNameSpace::TICKET, account, std::uint32_t(ticketSeq));
119 }
120 
121 uint256
122 getTicketIndex(AccountID const& account, SeqProxy ticketSeq)
123 {
124  assert(ticketSeq.isTicket());
125  return getTicketIndex(account, ticketSeq.value());
126 }
127 
128 //------------------------------------------------------------------------------
129 
130 namespace keylet {
131 
132 Keylet
133 account(AccountID const& id) noexcept
134 {
136 }
137 
138 Keylet
139 child(uint256 const& key) noexcept
140 {
141  return {ltCHILD, key};
142 }
143 
144 Keylet const&
145 skip() noexcept
146 {
147  static Keylet const ret{
149  return ret;
150 }
151 
152 Keylet
153 skip(LedgerIndex ledger) noexcept
154 {
155  return {
157  indexHash(
159  std::uint32_t(static_cast<std::uint32_t>(ledger) >> 16))};
160 }
161 
162 Keylet const&
163 amendments() noexcept
164 {
165  static Keylet const ret{
167  return ret;
168 }
169 
170 Keylet const&
171 fees() noexcept
172 {
173  static Keylet const ret{
175  return ret;
176 }
177 
178 Keylet const&
179 negativeUNL() noexcept
180 {
181  static Keylet const ret{
183  return ret;
184 }
185 
186 Keylet
187 book_t::operator()(Book const& b) const
188 {
189  return {ltDIR_NODE, getBookBase(b)};
190 }
191 
192 Keylet
194  AccountID const& id0,
195  AccountID const& id1,
196  Currency const& currency) noexcept
197 {
198  // There is code in SetTrust that calls us with id0 == id1, to allow users
199  // to locate and delete such "weird" trustlines. If we remove that code, we
200  // could enable this assert:
201  // assert(id0 != id1);
202 
203  // A trust line is shared between two accounts; while we typically think
204  // of this as an "issuer" and a "holder" the relationship is actually fully
205  // bidirectional.
206  //
207  // So that we can generate a unique ID for a trust line, regardess of which
208  // side of the line we're looking at, we define a "canonical" order for the
209  // two accounts (smallest then largest) and hash them in that order:
210  auto const accounts = std::minmax(id0, id1);
211 
212  return {
214  indexHash(
216  accounts.first,
217  accounts.second,
218  currency)};
219 }
220 
221 Keylet
222 offer(AccountID const& id, std::uint32_t seq) noexcept
223 {
224  return {ltOFFER, indexHash(LedgerNameSpace::OFFER, id, seq)};
225 }
226 
227 Keylet
228 quality(Keylet const& k, std::uint64_t q) noexcept
229 {
230  assert(k.type == ltDIR_NODE);
231 
232  // Indexes are stored in big endian format: they print as hex as stored.
233  // Most significant bytes are first and the least significant bytes
234  // represent adjacent entries. We place the quality, in big endian format,
235  // in the 8 right most bytes; this way, incrementing goes to the next entry
236  // for indexes.
237  uint256 x = k.key;
238 
239  // FIXME This is ugly and we can and should do better...
240  ((std::uint64_t*)x.end())[-1] = boost::endian::native_to_big(q);
241 
242  return {ltDIR_NODE, x};
243 }
244 
245 Keylet
246 next_t::operator()(Keylet const& k) const
247 {
248  assert(k.type == ltDIR_NODE);
249  return {ltDIR_NODE, getQualityNext(k.key)};
250 }
251 
252 Keylet
253 ticket_t::operator()(AccountID const& id, std::uint32_t ticketSeq) const
254 {
255  return {ltTICKET, getTicketIndex(id, ticketSeq)};
256 }
257 
258 Keylet
259 ticket_t::operator()(AccountID const& id, SeqProxy ticketSeq) const
260 {
261  return {ltTICKET, getTicketIndex(id, ticketSeq)};
262 }
263 
264 // This function is presently static, since it's never accessed from anywhere
265 // else. If we ever support multiple pages of signer lists, this would be the
266 // keylet used to locate them.
267 static Keylet
269 {
270  return {
272 }
273 
274 Keylet
275 signers(AccountID const& account) noexcept
276 {
277  return signers(account, 0);
278 }
279 
280 Keylet
281 check(AccountID const& id, std::uint32_t seq) noexcept
282 {
283  return {ltCHECK, indexHash(LedgerNameSpace::CHECK, id, seq)};
284 }
285 
286 Keylet
287 depositPreauth(AccountID const& owner, AccountID const& preauthorized) noexcept
288 {
289  return {
291  indexHash(LedgerNameSpace::DEPOSIT_PREAUTH, owner, preauthorized)};
292 }
293 
294 //------------------------------------------------------------------------------
295 
296 Keylet
297 unchecked(uint256 const& key) noexcept
298 {
299  return {ltANY, key};
300 }
301 
302 Keylet
303 ownerDir(AccountID const& id) noexcept
304 {
306 }
307 
308 Keylet
309 page(uint256 const& key, std::uint64_t index) noexcept
310 {
311  if (index == 0)
312  return {ltDIR_NODE, key};
313 
314  return {ltDIR_NODE, indexHash(LedgerNameSpace::DIR_NODE, key, index)};
315 }
316 
317 Keylet
318 escrow(AccountID const& src, std::uint32_t seq) noexcept
319 {
320  return {ltESCROW, indexHash(LedgerNameSpace::ESCROW, src, seq)};
321 }
322 
323 Keylet
324 payChan(AccountID const& src, AccountID const& dst, std::uint32_t seq) noexcept
325 {
326  return {
327  ltPAYCHAN,
329 }
330 
331 Keylet
332 nftpage_min(AccountID const& owner)
333 {
335  std::memcpy(buf.data(), owner.data(), owner.size());
336  return {ltNFTOKEN_PAGE, uint256{buf}};
337 }
338 
339 Keylet
340 nftpage_max(AccountID const& owner)
341 {
342  uint256 id = nft::pageMask;
343  std::memcpy(id.data(), owner.data(), owner.size());
344  return {ltNFTOKEN_PAGE, id};
345 }
346 
347 Keylet
348 nftpage(Keylet const& k, uint256 const& token)
349 {
350  assert(k.type == ltNFTOKEN_PAGE);
351  return {ltNFTOKEN_PAGE, (k.key & ~nft::pageMask) + (token & nft::pageMask)};
352 }
353 
354 Keylet
355 nftoffer(AccountID const& owner, std::uint32_t seq)
356 {
357  return {
359 }
360 
361 Keylet
362 nft_buys(uint256 const& id) noexcept
363 {
365 }
366 
367 Keylet
368 nft_sells(uint256 const& id) noexcept
369 {
371 }
372 
373 } // namespace keylet
374 
375 } // namespace ripple
ripple::keylet::ownerDir
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition: Indexes.cpp:303
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::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:163
ripple::ltANY
@ ltANY
A special type, matching any ledger entry type.
Definition: LedgerFormats.h:176
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:82
ripple::LedgerNameSpace::CHECK
@ CHECK
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:355
ripple::keylet::offer
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
Definition: Indexes.cpp:222
ripple::Issue::currency
Currency currency
Definition: Issue.h:37
ripple::keylet::skip
Keylet const & skip() noexcept
The index of the "short" skip list.
Definition: Indexes.cpp:145
ripple::keylet::child
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Definition: Indexes.cpp:139
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:100
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:189
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:115
ripple::keylet::next_t::operator()
Keylet operator()(Keylet const &k) const
Definition: Indexes.cpp:246
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:76
ripple::keylet::escrow
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Definition: Indexes.cpp:318
ripple::keylet::nftpage_min
Keylet nftpage_min(AccountID const &owner)
NFT page keylets.
Definition: Indexes.cpp:332
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:348
ripple::LedgerNameSpace::NEGATIVE_UNL
@ NEGATIVE_UNL
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:133
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:309
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:368
ripple::keylet::nftpage_max
Keylet nftpage_max(AccountID const &owner)
A keylet for the owner's last possible NFT page.
Definition: Indexes.cpp:340
ripple::keylet::ticket_t::operator()
Keylet operator()(AccountID const &id, std::uint32_t ticketSeq) const
Definition: Indexes.cpp:253
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:362
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:193
ripple::LedgerNameSpace::FEE_SETTINGS
@ FEE_SETTINGS
ripple::keylet::unchecked
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Definition: Indexes.cpp:297
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:187
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:324
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:171
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:228
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:268
ripple::keylet::negativeUNL
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Definition: Indexes.cpp:179
ripple::keylet::check
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Definition: Indexes.cpp:281
ripple::keylet::depositPreauth
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Definition: Indexes.cpp:287
ripple::getQuality
std::uint64_t getQuality(uint256 const &uBase)
Definition: Indexes.cpp:108
ripple::Book::in
Issue in
Definition: Book.h:36
ripple::Issue::account
AccountID account
Definition: Issue.h:38
ripple::ltPAYCHAN
@ ltPAYCHAN
A ledger object describing a single unidirectional XRP payment channel.
Definition: LedgerFormats.h:130