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/digest.h>
22 #include <boost/endian/conversion.hpp>
23 #include <algorithm>
24 #include <cassert>
25 
26 namespace ripple {
27 
46  ACCOUNT = 'a',
47  DIR_NODE = 'd',
48  TRUST_LINE = 'r',
49  OFFER = 'o',
50  OWNER_DIR = 'O',
51  BOOK_DIR = 'B',
52  SKIP_LIST = 's',
53  ESCROW = 'u',
54  AMENDMENTS = 'f',
55  FEE_SETTINGS = 'e',
56  TICKET = 'T',
57  SIGNER_LIST = 'S',
58  XRP_PAYMENT_CHANNEL = 'x',
59  CHECK = 'C',
60  DEPOSIT_PREAUTH = 'p',
61  NEGATIVE_UNL = 'N',
62 
63  // No longer used or supported. Left here to reserve the space
64  // to avoid accidental reuse.
65  CONTRACT [[deprecated]] = 'c',
66  GENERATOR [[deprecated]] = 'g',
67  NICKNAME [[deprecated]] = 'n',
68 };
69 
70 template <class... Args>
71 static uint256
72 indexHash(LedgerNameSpace space, Args const&... args)
73 {
74  return sha512Half(safe_cast<std::uint16_t>(space), args...);
75 }
76 
77 uint256
78 getBookBase(Book const& book)
79 {
80  assert(isConsistent(book));
81 
82  auto const index = indexHash(
84  book.in.currency,
85  book.out.currency,
86  book.in.account,
87  book.out.account);
88 
89  // Return with quality 0.
90  auto k = keylet::quality({ltDIR_NODE, index}, 0);
91 
92  return k.key;
93 }
94 
95 uint256
96 getQualityNext(uint256 const& uBase)
97 {
98  static uint256 const uNext(from_hex_text<uint256>("10000000000000000"));
99  return uBase + uNext;
100 }
101 
103 getQuality(uint256 const& uBase)
104 {
105  // VFALCO [base_uint] This assumes a certain storage format
106  return boost::endian::big_to_native(((std::uint64_t*)uBase.end())[-1]);
107 }
108 
109 uint256
110 getTicketIndex(AccountID const& account, std::uint32_t uSequence)
111 {
112  return indexHash(
113  LedgerNameSpace::TICKET, account, std::uint32_t(uSequence));
114 }
115 
116 //------------------------------------------------------------------------------
117 
118 namespace keylet {
119 
120 Keylet
121 account(AccountID const& id) noexcept
122 {
124 }
125 
126 Keylet
127 child(uint256 const& key) noexcept
128 {
129  return {ltCHILD, key};
130 }
131 
132 Keylet const&
133 skip() noexcept
134 {
135  static Keylet const ret{
137  return ret;
138 }
139 
140 Keylet
141 skip(LedgerIndex ledger) noexcept
142 {
143  return {
145  indexHash(
147  std::uint32_t(static_cast<std::uint32_t>(ledger) >> 16))};
148 }
149 
150 Keylet const&
151 amendments() noexcept
152 {
153  static Keylet const ret{
155  return ret;
156 }
157 
158 Keylet const&
159 fees() noexcept
160 {
161  static Keylet const ret{
163  return ret;
164 }
165 
166 Keylet const&
167 negativeUNL() noexcept
168 {
169  static Keylet const ret{
171  return ret;
172 }
173 
174 Keylet
175 book_t::operator()(Book const& b) const
176 {
177  return {ltDIR_NODE, getBookBase(b)};
178 }
179 
180 Keylet
182  AccountID const& id0,
183  AccountID const& id1,
184  Currency const& currency) noexcept
185 {
186  // There is code in SetTrust that calls us with id0 == id1, to allow users
187  // to locate and delete such "weird" trustlines. If we remove that code, we
188  // could enable this assert:
189  // assert(id0 != id1);
190 
191  // A trust line is shared between two accounts; while we typically think
192  // of this as an "issuer" and a "holder" the relationship is actually fully
193  // bidirectional.
194  //
195  // So that we can generate a unique ID for a trust line, regardess of which
196  // side of the line we're looking at, we define a "canonical" order for the
197  // two accounts (smallest then largest) and hash them in that order:
198  auto const accounts = std::minmax(id0, id1);
199 
200  return {
202  indexHash(
204  accounts.first,
205  accounts.second,
206  currency)};
207 }
208 
209 Keylet
210 offer(AccountID const& id, std::uint32_t seq) noexcept
211 {
212  return {ltOFFER, indexHash(LedgerNameSpace::OFFER, id, seq)};
213 }
214 
215 Keylet
216 quality(Keylet const& k, std::uint64_t q) noexcept
217 {
218  assert(k.type == ltDIR_NODE);
219 
220  // Indexes are stored in big endian format: they print as hex as stored.
221  // Most significant bytes are first and the least significant bytes
222  // represent adjacent entries. We place the quality, in big endian format,
223  // in the 8 right most bytes; this way, incrementing goes to the next entry
224  // for indexes.
225  uint256 x = k.key;
226 
227  // FIXME This is ugly and we can and should do better...
228  ((std::uint64_t*)x.end())[-1] = boost::endian::native_to_big(q);
229 
230  return {ltDIR_NODE, x};
231 }
232 
233 Keylet
234 next_t::operator()(Keylet const& k) const
235 {
236  assert(k.type == ltDIR_NODE);
237  return {ltDIR_NODE, getQualityNext(k.key)};
238 }
239 
240 Keylet
242 {
243  return {ltTICKET, getTicketIndex(id, seq)};
244 }
245 
246 // This function is presently static, since it's never accessed from anywhere
247 // else. If we ever support multiple pages of signer lists, this would be the
248 // keylet used to locate them.
249 static Keylet
251 {
252  return {
254 }
255 
256 Keylet
257 signers(AccountID const& account) noexcept
258 {
259  return signers(account, 0);
260 }
261 
262 Keylet
263 check(AccountID const& id, std::uint32_t seq) noexcept
264 {
265  return {ltCHECK, indexHash(LedgerNameSpace::CHECK, id, seq)};
266 }
267 
268 Keylet
269 depositPreauth(AccountID const& owner, AccountID const& preauthorized) noexcept
270 {
271  return {
273  indexHash(LedgerNameSpace::DEPOSIT_PREAUTH, owner, preauthorized)};
274 }
275 
276 //------------------------------------------------------------------------------
277 
278 Keylet
279 unchecked(uint256 const& key) noexcept
280 {
281  return {ltANY, key};
282 }
283 
284 Keylet
285 ownerDir(AccountID const& id) noexcept
286 {
288 }
289 
290 Keylet
291 page(uint256 const& key, std::uint64_t index) noexcept
292 {
293  if (index == 0)
294  return {ltDIR_NODE, key};
295 
296  return {ltDIR_NODE, indexHash(LedgerNameSpace::DIR_NODE, key, index)};
297 }
298 
299 Keylet
300 escrow(AccountID const& src, std::uint32_t seq) noexcept
301 {
302  return {ltESCROW, indexHash(LedgerNameSpace::ESCROW, src, seq)};
303 }
304 
305 Keylet
306 payChan(AccountID const& src, AccountID const& dst, std::uint32_t seq) noexcept
307 {
308  return {
309  ltPAYCHAN,
311 }
312 
313 } // namespace keylet
314 
315 } // namespace ripple
ripple::keylet::ownerDir
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition: Indexes.cpp:285
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:151
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:78
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:210
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:133
ripple::keylet::child
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Definition: Indexes.cpp:127
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:96
ripple::ltSIGNER_LIST
@ ltSIGNER_LIST
Definition: LedgerFormats.h:70
ripple::LedgerNameSpace
LedgerNameSpace
Type-specific prefix for calculating ledger indices.
Definition: Indexes.cpp:45
ripple::LedgerNameSpace::SKIP_LIST
@ SKIP_LIST
algorithm
ripple::ltTICKET
@ ltTICKET
Definition: LedgerFormats.h:68
ripple::keylet::next_t::operator()
Keylet operator()(Keylet const &k) const
Definition: Indexes.cpp:234
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::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:72
ripple::keylet::ticket_t::operator()
Keylet operator()(AccountID const &id, std::uint32_t seq) const
Definition: Indexes.cpp:241
ripple::keylet::escrow
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Definition: Indexes.cpp:300
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:121
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:291
ripple::LedgerNameSpace::CONTRACT
@ CONTRACT
ripple::LedgerNameSpace::OWNER_DIR
@ OWNER_DIR
ripple::Keylet::type
LedgerEntryType type
Definition: Keylet.h:40
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:181
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:279
ripple::ltNEGATIVE_UNL
@ ltNEGATIVE_UNL
Definition: LedgerFormats.h:89
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:175
ripple::keylet::payChan
Keylet payChan(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Definition: Indexes.cpp:306
ripple::getTicketIndex
uint256 getTicketIndex(AccountID const &account, std::uint32_t uSequence)
Definition: Indexes.cpp:110
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::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:159
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:216
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:250
ripple::keylet::negativeUNL
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Definition: Indexes.cpp:167
ripple::keylet::check
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Definition: Indexes.cpp:263
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:269
ripple::getQuality
std::uint64_t getQuality(uint256 const &uBase)
Definition: Indexes.cpp:103
ripple::Book::in
Issue in
Definition: Book.h:35
ripple::Issue::account
AccountID account
Definition: Issue.h:38