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