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 uNext(from_hex_text<uint256>("10000000000000000"));
100  return uBase + uNext;
101 }
102 
104 getQuality(uint256 const& uBase)
105 {
106  // VFALCO [base_uint] This assumes a certain storage format
107  return boost::endian::big_to_native(((std::uint64_t*)uBase.end())[-1]);
108 }
109 
110 uint256
111 getTicketIndex(AccountID const& account, std::uint32_t ticketSeq)
112 {
113  return indexHash(
114  LedgerNameSpace::TICKET, account, std::uint32_t(ticketSeq));
115 }
116 
117 uint256
118 getTicketIndex(AccountID const& account, SeqProxy ticketSeq)
119 {
120  assert(ticketSeq.isTicket());
121  return getTicketIndex(account, ticketSeq.value());
122 }
123 
124 //------------------------------------------------------------------------------
125 
126 namespace keylet {
127 
128 Keylet
129 account(AccountID const& id) noexcept
130 {
132 }
133 
134 Keylet
135 child(uint256 const& key) noexcept
136 {
137  return {ltCHILD, key};
138 }
139 
140 Keylet const&
141 skip() noexcept
142 {
143  static Keylet const ret{
145  return ret;
146 }
147 
148 Keylet
149 skip(LedgerIndex ledger) noexcept
150 {
151  return {
153  indexHash(
155  std::uint32_t(static_cast<std::uint32_t>(ledger) >> 16))};
156 }
157 
158 Keylet const&
159 amendments() noexcept
160 {
161  static Keylet const ret{
163  return ret;
164 }
165 
166 Keylet const&
167 fees() noexcept
168 {
169  static Keylet const ret{
171  return ret;
172 }
173 
174 Keylet const&
175 negativeUNL() noexcept
176 {
177  static Keylet const ret{
179  return ret;
180 }
181 
182 Keylet
183 book_t::operator()(Book const& b) const
184 {
185  return {ltDIR_NODE, getBookBase(b)};
186 }
187 
188 Keylet
190  AccountID const& id0,
191  AccountID const& id1,
192  Currency const& currency) noexcept
193 {
194  // There is code in SetTrust that calls us with id0 == id1, to allow users
195  // to locate and delete such "weird" trustlines. If we remove that code, we
196  // could enable this assert:
197  // assert(id0 != id1);
198 
199  // A trust line is shared between two accounts; while we typically think
200  // of this as an "issuer" and a "holder" the relationship is actually fully
201  // bidirectional.
202  //
203  // So that we can generate a unique ID for a trust line, regardess of which
204  // side of the line we're looking at, we define a "canonical" order for the
205  // two accounts (smallest then largest) and hash them in that order:
206  auto const accounts = std::minmax(id0, id1);
207 
208  return {
210  indexHash(
212  accounts.first,
213  accounts.second,
214  currency)};
215 }
216 
217 Keylet
218 offer(AccountID const& id, std::uint32_t seq) noexcept
219 {
220  return {ltOFFER, indexHash(LedgerNameSpace::OFFER, id, seq)};
221 }
222 
223 Keylet
224 quality(Keylet const& k, std::uint64_t q) noexcept
225 {
226  assert(k.type == ltDIR_NODE);
227 
228  // Indexes are stored in big endian format: they print as hex as stored.
229  // Most significant bytes are first and the least significant bytes
230  // represent adjacent entries. We place the quality, in big endian format,
231  // in the 8 right most bytes; this way, incrementing goes to the next entry
232  // for indexes.
233  uint256 x = k.key;
234 
235  // FIXME This is ugly and we can and should do better...
236  ((std::uint64_t*)x.end())[-1] = boost::endian::native_to_big(q);
237 
238  return {ltDIR_NODE, x};
239 }
240 
241 Keylet
242 next_t::operator()(Keylet const& k) const
243 {
244  assert(k.type == ltDIR_NODE);
245  return {ltDIR_NODE, getQualityNext(k.key)};
246 }
247 
248 Keylet
249 ticket_t::operator()(AccountID const& id, std::uint32_t ticketSeq) const
250 {
251  return {ltTICKET, getTicketIndex(id, ticketSeq)};
252 }
253 
254 Keylet
255 ticket_t::operator()(AccountID const& id, SeqProxy ticketSeq) const
256 {
257  return {ltTICKET, getTicketIndex(id, ticketSeq)};
258 }
259 
260 // This function is presently static, since it's never accessed from anywhere
261 // else. If we ever support multiple pages of signer lists, this would be the
262 // keylet used to locate them.
263 static Keylet
265 {
266  return {
268 }
269 
270 Keylet
271 signers(AccountID const& account) noexcept
272 {
273  return signers(account, 0);
274 }
275 
276 Keylet
277 check(AccountID const& id, std::uint32_t seq) noexcept
278 {
279  return {ltCHECK, indexHash(LedgerNameSpace::CHECK, id, seq)};
280 }
281 
282 Keylet
283 depositPreauth(AccountID const& owner, AccountID const& preauthorized) noexcept
284 {
285  return {
287  indexHash(LedgerNameSpace::DEPOSIT_PREAUTH, owner, preauthorized)};
288 }
289 
290 //------------------------------------------------------------------------------
291 
292 Keylet
293 unchecked(uint256 const& key) noexcept
294 {
295  return {ltANY, key};
296 }
297 
298 Keylet
299 ownerDir(AccountID const& id) noexcept
300 {
302 }
303 
304 Keylet
305 page(uint256 const& key, std::uint64_t index) noexcept
306 {
307  if (index == 0)
308  return {ltDIR_NODE, key};
309 
310  return {ltDIR_NODE, indexHash(LedgerNameSpace::DIR_NODE, key, index)};
311 }
312 
313 Keylet
314 escrow(AccountID const& src, std::uint32_t seq) noexcept
315 {
316  return {ltESCROW, indexHash(LedgerNameSpace::ESCROW, src, seq)};
317 }
318 
319 Keylet
320 payChan(AccountID const& src, AccountID const& dst, std::uint32_t seq) noexcept
321 {
322  return {
323  ltPAYCHAN,
325 }
326 
327 } // namespace keylet
328 
329 } // namespace ripple
ripple::keylet::ownerDir
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition: Indexes.cpp:299
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:159
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:119
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:218
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:141
ripple::keylet::child
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Definition: Indexes.cpp:135
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:111
ripple::ltTICKET
@ ltTICKET
Definition: LedgerFormats.h:68
ripple::keylet::next_t::operator()
Keylet operator()(Keylet const &k) const
Definition: Indexes.cpp:242
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:493
ripple::SeqProxy::isTicket
constexpr bool isTicket() const
Definition: SeqProxy.h:94
ripple::Keylet::key
uint256 key
Definition: Keylet.h:41
ripple::base_uint< 256 >
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:314
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:129
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:305
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:249
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:189
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:293
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:183
ripple::keylet::payChan
Keylet payChan(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Definition: Indexes.cpp:320
ripple::sha512Half
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:227
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:167
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:224
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:264
ripple::keylet::negativeUNL
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Definition: Indexes.cpp:175
ripple::keylet::check
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Definition: Indexes.cpp:277
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:283
ripple::getQuality
std::uint64_t getQuality(uint256 const &uBase)
Definition: Indexes.cpp:104
ripple::Book::in
Issue in
Definition: Book.h:35
ripple::Issue::account
AccountID account
Definition: Issue.h:38