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