rippled
base_uint.h
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 // Copyright (c) 2009-2010 Satoshi Nakamoto
21 // Copyright (c) 2011 The Bitcoin developers
22 // Distributed under the MIT/X11 software license, see the accompanying
23 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
24 
25 #ifndef RIPPLE_BASICS_BASE_UINT_H_INCLUDED
26 #define RIPPLE_BASICS_BASE_UINT_H_INCLUDED
27 
28 #include <ripple/basics/hardened_hash.h>
29 #include <ripple/basics/strHex.h>
30 #include <ripple/beast/utility/Zero.h>
31 #include <boost/endian/conversion.hpp>
32 #include <boost/functional/hash.hpp>
33 #include <array>
34 #include <cstring>
35 #include <functional>
36 #include <type_traits>
37 
38 namespace ripple {
39 
40 namespace detail {
41 
42 template <class Container, class = std::void_t<>>
44 {
45 };
46 
47 template <class Container>
49  Container,
50  std::void_t<
51  decltype(std::declval<Container const>().size()),
52  decltype(std::declval<Container const>().data()),
53  typename Container::value_type>> : std::true_type
54 {
55 };
56 
57 } // namespace detail
58 
72 template <std::size_t Bits, class Tag = void>
73 class base_uint
74 {
75  static_assert(
76  (Bits % 32) == 0,
77  "The length of a base_uint in bits must be a multiple of 32.");
78 
79  static_assert(
80  Bits >= 64,
81  "The length of a base_uint in bits must be at least 64.");
82 
83  static constexpr std::size_t WIDTH = Bits / 32;
84 
85  // This is really big-endian in byte order.
86  // We sometimes use std::uint32_t for speed.
87 
89 
90 public:
91  //--------------------------------------------------------------------------
92  //
93  // STL Container Interface
94  //
95 
96  static std::size_t constexpr bytes = Bits / 8;
97  static_assert(sizeof(data_) == bytes, "");
98 
101  using value_type = unsigned char;
102  using pointer = value_type*;
104  using const_pointer = value_type const*;
105  using const_reference = value_type const&;
106  using iterator = pointer;
110  using tag_type = Tag;
111 
112  pointer
114  {
115  return reinterpret_cast<pointer>(data_.data());
116  }
118  data() const
119  {
120  return reinterpret_cast<const_pointer>(data_.data());
121  }
122 
123  iterator
125  {
126  return data();
127  }
128  iterator
129  end()
130  {
131  return data() + bytes;
132  }
134  begin() const
135  {
136  return data();
137  }
139  end() const
140  {
141  return data() + bytes;
142  }
144  cbegin() const
145  {
146  return data();
147  }
149  cend() const
150  {
151  return data() + bytes;
152  }
153 
159 
160  //--------------------------------------------------------------------------
161 
162 private:
169  // NIKB TODO Remove the need for this constructor.
170  struct VoidHelper
171  {
172  explicit VoidHelper() = default;
173  };
174 
175  explicit base_uint(void const* data, VoidHelper)
176  {
177  memcpy(data_.data(), data, bytes);
178  }
179 
180 public:
182  {
183  *this = beast::zero;
184  }
185 
187  {
188  *this = beast::zero;
189  }
190 
192  {
193  *this = b;
194  }
195 
196  template <
197  class Container,
198  class = std::enable_if_t<
201  explicit base_uint(Container const& c)
202  {
203  assert(c.size() * sizeof(typename Container::value_type) == size());
204  std::memcpy(data_.data(), c.data(), size());
205  }
206 
207  template <class Container>
211  base_uint&>
212  operator=(Container const& c)
213  {
214  assert(c.size() * sizeof(typename Container::value_type) == size());
215  std::memcpy(data_.data(), c.data(), size());
216  return *this;
217  }
218 
219  /* Construct from a raw pointer.
220  The buffer pointed to by `data` must be at least Bits/8 bytes.
221  */
222  static base_uint
223  fromVoid(void const* data)
224  {
225  return base_uint(data, VoidHelper());
226  }
227 
228  int
229  signum() const
230  {
231  for (int i = 0; i < WIDTH; i++)
232  if (data_[i] != 0)
233  return 1;
234 
235  return 0;
236  }
237 
238  bool
239  operator!() const
240  {
241  return *this == beast::zero;
242  }
243 
244  const base_uint
245  operator~() const
246  {
247  base_uint ret;
248 
249  for (int i = 0; i < WIDTH; i++)
250  ret.data_[i] = ~data_[i];
251 
252  return ret;
253  }
254 
255  base_uint&
257  {
258  *this = beast::zero;
259  union
260  {
261  unsigned u[2];
262  std::uint64_t ul;
263  };
264  // Put in least significant bits.
265  ul = boost::endian::native_to_big(uHost);
266  data_[WIDTH - 2] = u[0];
267  data_[WIDTH - 1] = u[1];
268  return *this;
269  }
270 
271  base_uint&
273  {
274  for (int i = 0; i < WIDTH; i++)
275  data_[i] ^= b.data_[i];
276 
277  return *this;
278  }
279 
280  base_uint&
282  {
283  for (int i = 0; i < WIDTH; i++)
284  data_[i] &= b.data_[i];
285 
286  return *this;
287  }
288 
289  base_uint&
291  {
292  for (int i = 0; i < WIDTH; i++)
293  data_[i] |= b.data_[i];
294 
295  return *this;
296  }
297 
298  base_uint&
300  {
301  // prefix operator
302  for (int i = WIDTH - 1; i >= 0; --i)
303  {
304  data_[i] = boost::endian::native_to_big(
305  boost::endian::big_to_native(data_[i]) + 1);
306  if (data_[i] != 0)
307  break;
308  }
309 
310  return *this;
311  }
312 
313  const base_uint
315  {
316  // postfix operator
317  const base_uint ret = *this;
318  ++(*this);
319 
320  return ret;
321  }
322 
323  base_uint&
325  {
326  for (int i = WIDTH - 1; i >= 0; --i)
327  {
328  auto prev = data_[i];
329  data_[i] = boost::endian::native_to_big(
330  boost::endian::big_to_native(data_[i]) - 1);
331 
332  if (prev != 0)
333  break;
334  }
335 
336  return *this;
337  }
338 
339  const base_uint
341  {
342  // postfix operator
343  const base_uint ret = *this;
344  --(*this);
345 
346  return ret;
347  }
348 
349  base_uint&
351  {
352  std::uint64_t carry = 0;
353 
354  for (int i = WIDTH; i--;)
355  {
356  std::uint64_t n = carry + boost::endian::big_to_native(data_[i]) +
357  boost::endian::big_to_native(b.data_[i]);
358 
359  data_[i] =
360  boost::endian::native_to_big(static_cast<std::uint32_t>(n));
361  carry = n >> 32;
362  }
363 
364  return *this;
365  }
366 
367  template <class Hasher>
368  friend void
369  hash_append(Hasher& h, base_uint const& a) noexcept
370  {
371  // Do not allow any endian transformations on this memory
372  h(a.data_.data(), sizeof(a.data_));
373  }
374 
383  [[nodiscard]] bool
385  {
386  if (sv == "0")
387  {
388  zero();
389  return true;
390  }
391 
392  if (sv.size() != bytes * 2)
393  return false;
394 
395  auto out = data();
396 
397  auto in = sv.begin();
398 
399  while (in != sv.end())
400  {
401  auto const hi = charUnHex(*in++);
402  auto const lo = charUnHex(*in++);
403 
404  if (hi == -1 || lo == -1)
405  return false;
406 
407  *out++ = static_cast<std::uint8_t>((hi << 4) + lo);
408  }
409 
410  return true;
411  }
412 
413  [[nodiscard]] bool
414  parseHex(const char* str)
415  {
416  return parseHex(std::string_view{str});
417  }
418 
419  [[nodiscard]] bool
420  parseHex(std::string const& str)
421  {
422  return parseHex(std::string_view{str});
423  }
424 
425  constexpr static std::size_t
427  {
428  return bytes;
429  }
430 
432  {
433  data_.fill(0);
434  return *this;
435  }
436 
437  // Deprecated.
438  bool
439  isZero() const
440  {
441  return *this == beast::zero;
442  }
443  bool
444  isNonZero() const
445  {
446  return *this != beast::zero;
447  }
448  void
450  {
451  *this = beast::zero;
452  }
453 };
454 
458 
459 template <std::size_t Bits, class Tag>
460 inline int
462 {
463  auto ret = std::mismatch(a.cbegin(), a.cend(), b.cbegin());
464 
465  if (ret.first == a.cend())
466  return 0;
467 
468  // a > b
469  if (*ret.first > *ret.second)
470  return 1;
471 
472  // a < b
473  return -1;
474 }
475 
476 template <std::size_t Bits, class Tag>
477 inline bool
479 {
480  return compare(a, b) < 0;
481 }
482 
483 template <std::size_t Bits, class Tag>
484 inline bool
486 {
487  return compare(a, b) <= 0;
488 }
489 
490 template <std::size_t Bits, class Tag>
491 inline bool
493 {
494  return compare(a, b) > 0;
495 }
496 
497 template <std::size_t Bits, class Tag>
498 inline bool
500 {
501  return compare(a, b) >= 0;
502 }
503 
504 template <std::size_t Bits, class Tag>
505 inline bool
507 {
508  return compare(a, b) == 0;
509 }
510 
511 template <std::size_t Bits, class Tag>
512 inline bool
514 {
515  return compare(a, b) != 0;
516 }
517 
518 //------------------------------------------------------------------------------
519 template <std::size_t Bits, class Tag>
520 inline bool
522 {
523  return a == base_uint<Bits, Tag>(b);
524 }
525 
526 template <std::size_t Bits, class Tag>
527 inline bool
529 {
530  return !(a == b);
531 }
532 
533 //------------------------------------------------------------------------------
534 template <std::size_t Bits, class Tag>
535 inline const base_uint<Bits, Tag>
537 {
538  return base_uint<Bits, Tag>(a) ^= b;
539 }
540 
541 template <std::size_t Bits, class Tag>
542 inline const base_uint<Bits, Tag>
544 {
545  return base_uint<Bits, Tag>(a) &= b;
546 }
547 
548 template <std::size_t Bits, class Tag>
549 inline const base_uint<Bits, Tag>
551 {
552  return base_uint<Bits, Tag>(a) |= b;
553 }
554 
555 template <std::size_t Bits, class Tag>
556 inline const base_uint<Bits, Tag>
558 {
559  return base_uint<Bits, Tag>(a) += b;
560 }
561 
562 //------------------------------------------------------------------------------
563 template <std::size_t Bits, class Tag>
564 inline std::string
566 {
567  return strHex(a.cbegin(), a.cend());
568 }
569 
570 template <std::size_t Bits, class Tag>
571 inline std::ostream&
573 {
574  return out << to_string(u);
575 }
576 
577 #ifndef __INTELLISENSE__
578 static_assert(sizeof(uint128) == 128 / 8, "There should be no padding bytes");
579 static_assert(sizeof(uint160) == 160 / 8, "There should be no padding bytes");
580 static_assert(sizeof(uint256) == 256 / 8, "There should be no padding bytes");
581 #endif
582 
583 } // namespace ripple
584 
585 namespace beast {
586 
587 template <std::size_t Bits, class Tag>
588 struct is_uniquely_represented<ripple::base_uint<Bits, Tag>>
589  : public std::true_type
590 {
591  explicit is_uniquely_represented() = default;
592 };
593 
594 } // namespace beast
595 
596 #endif
ripple::base_uint::signum
int signum() const
Definition: base_uint.h:229
ripple::operator>
bool operator>(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:492
ripple::base_uint< 256 >::iterator
pointer iterator
Definition: base_uint.h:106
std::false_type
ripple::base_uint::operator--
base_uint & operator--()
Definition: base_uint.h:324
ripple::operator|
const base_uint< Bits, Tag > operator|(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:550
ripple::Dir::const_iterator
Definition: Directory.h:49
ripple::base_uint::operator--
const base_uint operator--(int)
Definition: base_uint.h:340
std::string
STL class.
ripple::base_uint::hash_append
friend void hash_append(Hasher &h, base_uint const &a) noexcept
Definition: base_uint.h:369
ripple::uint160
base_uint< 160 > uint160
Definition: base_uint.h:456
ripple::charUnHex
int charUnHex(unsigned char c)
Converts a hex digit to the corresponding integer.
Definition: strHex.cpp:26
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:444
cstring
ripple::base_uint< 256 >::value_type
unsigned char value_type
Definition: base_uint.h:101
std::string_view
STL class.
ripple::base_uint::VoidHelper
Construct from a raw pointer.
Definition: base_uint.h:170
functional
ripple::operator>=
bool operator>=(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:499
ripple::base_uint::base_uint
base_uint(Container const &c)
Definition: base_uint.h:201
std::string_view::size
T size(T... args)
ripple::base_uint::end
iterator end()
Definition: base_uint.h:129
ripple::base_uint::data
const_pointer data() const
Definition: base_uint.h:118
ripple::base_uint::operator=
std::enable_if_t< detail::is_contiguous_container< Container >::value &&std::is_trivially_copyable< typename Container::value_type >::value, base_uint & > operator=(Container const &c)
Definition: base_uint.h:212
ripple::QualityDirection::in
@ in
ripple::base_uint::cbegin
const_iterator cbegin() const
Definition: base_uint.h:144
ripple::base_uint< 256 >::pointer
value_type * pointer
Definition: base_uint.h:102
ripple::base_uint::WIDTH
static constexpr std::size_t WIDTH
Definition: base_uint.h:83
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:45
ripple::base_uint::base_uint
base_uint(beast::Zero)
Definition: base_uint.h:186
ripple::operator<<
std::ostream & operator<<(std::ostream &os, TOffer< TIn, TOut > const &offer)
Definition: Offer.h:242
ripple::base_uint::data
pointer data()
Definition: base_uint.h:113
ripple::operator==
bool operator==(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:155
std::array::fill
T fill(T... args)
ripple::base_uint::size
constexpr static std::size_t size()
Definition: base_uint.h:426
ripple::base_uint< 256 >::const_iterator
const_pointer const_iterator
Definition: base_uint.h:107
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:457
beast::is_uniquely_represented
Definition: hash_append.h:95
ripple::base_uint::operator~
const base_uint operator~() const
Definition: base_uint.h:245
ripple::base_uint::parseHex
bool parseHex(std::string const &str)
Definition: base_uint.h:420
beast::is_uniquely_represented::is_uniquely_represented
is_uniquely_represented()=default
std::mismatch
T mismatch(T... args)
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:73
ripple::base_uint< 256 >::const_reference
value_type const & const_reference
Definition: base_uint.h:105
ripple::operator<=
bool operator<=(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:485
ripple::base_uint::operator|=
base_uint & operator|=(const base_uint &b)
Definition: base_uint.h:290
ripple::base_uint::VoidHelper::VoidHelper
VoidHelper()=default
ripple::QualityDirection::out
@ out
ripple::operator+
const base_uint< Bits, Tag > operator+(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:557
ripple::base_uint::bytes
static constexpr std::size_t bytes
Definition: base_uint.h:96
ripple::base_uint::data_
std::array< std::uint32_t, WIDTH > data_
Definition: base_uint.h:88
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:439
std::is_trivially_copyable
std::enable_if_t
ripple::operator<
bool operator<(CanonicalTXSet::Key const &lhs, CanonicalTXSet::Key const &rhs)
Definition: CanonicalTXSet.cpp:25
std::ostream
STL class.
ripple::compare
int compare(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:461
ripple::base_uint::operator&=
base_uint & operator&=(const base_uint &b)
Definition: base_uint.h:281
ripple::base_uint::begin
const_iterator begin() const
Definition: base_uint.h:134
ripple::operator!=
bool operator!=(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:165
array
beast::Zero
Zero allows classes to offer efficient comparisons to zero.
Definition: Zero.h:42
ripple::hardened_hash
Seed functor once per construction.
Definition: hardened_hash.h:96
std::uint64_t
ripple::operator^
const base_uint< Bits, Tag > operator^(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:536
ripple::uint128
base_uint< 128 > uint128
Definition: base_uint.h:455
ripple::operator&
const base_uint< Bits, Tag > operator&(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:543
ripple::base_uint< 256 >::tag_type
void tag_type
Definition: base_uint.h:110
ripple::base_uint::operator++
base_uint & operator++()
Definition: base_uint.h:299
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::detail::is_contiguous_container
Definition: base_uint.h:43
ripple::base_uint::parseHex
bool parseHex(const char *str)
Definition: base_uint.h:414
ripple::base_uint::parseHex
bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:384
ripple::base_uint::begin
iterator begin()
Definition: base_uint.h:124
ripple::base_uint::base_uint
base_uint(void const *data, VoidHelper)
Definition: base_uint.h:175
ripple::base_uint::operator=
base_uint< Bits, Tag > & operator=(beast::Zero)
Definition: base_uint.h:431
ripple::base_uint::zero
void zero()
Definition: base_uint.h:449
std::string_view::begin
T begin(T... args)
ripple::base_uint::base_uint
base_uint(std::uint64_t b)
Definition: base_uint.h:191
std
STL namespace.
ripple::base_uint::fromVoid
static base_uint fromVoid(void const *data)
Definition: base_uint.h:223
ripple::base_uint::end
const_iterator end() const
Definition: base_uint.h:139
std::ptrdiff_t
std::size_t
ripple::base_uint::operator^=
base_uint & operator^=(const base_uint &b)
Definition: base_uint.h:272
std::memcpy
T memcpy(T... args)
ripple::base_uint::operator++
const base_uint operator++(int)
Definition: base_uint.h:314
ripple::base_uint::cend
const_iterator cend() const
Definition: base_uint.h:149
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:45
std::string_view::end
T end(T... args)
std::reverse_iterator
ripple::base_uint::operator=
base_uint & operator=(std::uint64_t uHost)
Definition: base_uint.h:256
ripple::base_uint::operator+=
base_uint & operator+=(const base_uint &b)
Definition: base_uint.h:350
ripple::base_uint::operator!
bool operator!() const
Definition: base_uint.h:239
ripple::base_uint< 256 >::const_pointer
value_type const * const_pointer
Definition: base_uint.h:104
ripple::base_uint< 256 >::reference
value_type & reference
Definition: base_uint.h:103
std::array::data
T data(T... args)
type_traits
ripple::base_uint::base_uint
base_uint()
Definition: base_uint.h:181
beast
Definition: base_uint.h:585