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 <boost/endian/conversion.hpp>
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 
64  // No longer used or supported. Left here to reserve the space
65  // to avoid accidental reuse.
66  CONTRACT [[deprecated]] = 'c',
67  GENERATOR [[deprecated]] = 'g',
68  NICKNAME [[deprecated]] = 'n',
69 };
70 
71 template <class... Args>
72 static uint256
73 indexHash(LedgerNameSpace space, Args const&... args)
74 {
75  return sha512Half(safe_cast<std::uint16_t>(space), args...);
76 }
77 
78 uint256
79 getBookBase(Book const& book)
80 {
81  assert(isConsistent(book));
82 
83  auto const index = indexHash(
85  book.in.currency,
86  book.out.currency,
87  book.in.account,
88  book.out.account);
89 
90  // Return with quality 0.
91  auto k = keylet::quality({ltDIR_NODE, index}, 0);
92 
93  return k.key;
94 }
95 
96 uint256
97 getQualityNext(uint256 const& uBase)
98 {
99  static uint256 const nextq = []() {
100  uint256 x;
101  (void)x.parseHex(
102  "0000000000000000000000000000000000000000000000010000000000000000");
103  return x;
104  }();
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 } // namespace keylet
333 
334 } // 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::NICKNAME
@ NICKNAME
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::LedgerNameSpace::OFFER
@ OFFER
ripple::keylet::amendments
Keylet const & amendments() noexcept
The index of the amendment table.
Definition: Indexes.cpp:164
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:36
ripple::getBookBase
uint256 getBookBase(Book const &book)
Definition: Indexes.cpp:79
ripple::LedgerNameSpace::CHECK
@ CHECK
ripple::ltESCROW
@ ltESCROW
Definition: LedgerFormats.h:80
ripple::base_uint::end
iterator end()
Definition: base_uint.h:129
ripple::ltANY
@ ltANY
Special type, anything This is used when the type in the Keylet is unknown, such as when building met...
Definition: LedgerFormats.h:41
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:37
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::ltLEDGER_HASHES
@ ltLEDGER_HASHES
Definition: LedgerFormats.h:74
ripple::ltAMENDMENTS
@ ltAMENDMENTS
Definition: LedgerFormats.h:76
ripple::getQualityNext
uint256 getQualityNext(uint256 const &uBase)
Definition: Indexes.cpp:97
ripple::ltSIGNER_LIST
@ ltSIGNER_LIST
Definition: LedgerFormats.h:70
ripple::LedgerNameSpace
LedgerNameSpace
Type-specific prefix for calculating ledger indices.
Definition: Indexes.cpp:46
ripple::LedgerNameSpace::SKIP_LIST
@ SKIP_LIST
algorithm
ripple::getTicketIndex
uint256 getTicketIndex(AccountID const &account, std::uint32_t ticketSeq)
Definition: Indexes.cpp:116
ripple::ltTICKET
@ ltTICKET
Definition: LedgerFormats.h:68
ripple::keylet::next_t::operator()
Keylet operator()(Keylet const &k) const
Definition: Indexes.cpp:247
ripple::ltCHECK
@ ltCHECK
Definition: LedgerFormats.h:85
ripple::ltCHILD
@ ltCHILD
Special type, anything not a directory This is used when the type in the Keylet is unknown,...
Definition: LedgerFormats.h:47
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:457
ripple::SeqProxy::isTicket
constexpr bool isTicket() const
Definition: SeqProxy.h:94
ripple::Keylet::key
uint256 key
Definition: Keylet.h:41
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:73
ripple::indexHash
static uint256 indexHash(LedgerNameSpace space, Args const &... args)
Definition: Indexes.cpp:73
ripple::keylet::escrow
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Definition: Indexes.cpp:319
ripple::LedgerNameSpace::NEGATIVE_UNL
@ NEGATIVE_UNL
ripple::ltFEE_SETTINGS
@ ltFEE_SETTINGS
Definition: LedgerFormats.h:78
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:134
std::minmax
T minmax(T... args)
ripple::LedgerNameSpace::DEPOSIT_PREAUTH
@ DEPOSIT_PREAUTH
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
ripple::Keylet::type
LedgerEntryType type
Definition: Keylet.h:40
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::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::ltDEPOSIT_PREAUTH
@ ltDEPOSIT_PREAUTH
Definition: LedgerFormats.h:87
ripple::keylet::unchecked
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Definition: Indexes.cpp:298
ripple::ltNEGATIVE_UNL
@ ltNEGATIVE_UNL
Definition: LedgerFormats.h:89
ripple::SeqProxy::value
constexpr std::uint32_t value() const
Definition: SeqProxy.h:82
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::ltRIPPLE_STATE
@ ltRIPPLE_STATE
Definition: LedgerFormats.h:66
ripple::keylet::book_t::operator()
Keylet operator()(Book const &b) const
Definition: Indexes.cpp:188
ripple::base_uint::parseHex
bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:384
ripple::keylet::payChan
Keylet payChan(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Definition: Indexes.cpp:325
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::ltPAYCHAN
@ ltPAYCHAN
Definition: LedgerFormats.h:83
ripple::keylet::fees
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Definition: Indexes.cpp:172
ripple::LedgerNameSpace::ESCROW
@ ESCROW
ripple::Book
Specifies an order book.
Definition: Book.h:32
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::ltDIR_NODE
@ ltDIR_NODE
Directory node.
Definition: LedgerFormats.h:64
ripple::LedgerNameSpace::ACCOUNT
@ ACCOUNT
ripple::ltOFFER
@ ltOFFER
Definition: LedgerFormats.h:72
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::ltACCOUNT_ROOT
@ ltACCOUNT_ROOT
Definition: LedgerFormats.h:53
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::Book::in
Issue in
Definition: Book.h:35
ripple::Issue::account
AccountID account
Definition: Issue.h:38