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/Expected.h>
29 #include <ripple/basics/contract.h>
30 #include <ripple/basics/hardened_hash.h>
31 #include <ripple/basics/strHex.h>
32 #include <ripple/beast/utility/Zero.h>
33 #include <boost/endian/conversion.hpp>
34 #include <boost/functional/hash.hpp>
35 #include <array>
36 #include <cstring>
37 #include <functional>
38 #include <type_traits>
39 
40 namespace ripple {
41 
42 namespace detail {
43 
44 template <class Container, class = std::void_t<>>
46 {
47 };
48 
49 template <class Container>
51  Container,
52  std::void_t<
53  decltype(std::declval<Container const>().size()),
54  decltype(std::declval<Container const>().data()),
55  typename Container::value_type>> : std::true_type
56 {
57 };
58 
59 } // namespace detail
60 
74 template <std::size_t Bits, class Tag = void>
75 class base_uint
76 {
77  static_assert(
78  (Bits % 32) == 0,
79  "The length of a base_uint in bits must be a multiple of 32.");
80 
81  static_assert(
82  Bits >= 64,
83  "The length of a base_uint in bits must be at least 64.");
84 
85  static constexpr std::size_t WIDTH = Bits / 32;
86 
87  // This is really big-endian in byte order.
88  // We sometimes use std::uint32_t for speed.
89 
91 
92 public:
93  //--------------------------------------------------------------------------
94  //
95  // STL Container Interface
96  //
97 
98  static std::size_t constexpr bytes = Bits / 8;
99  static_assert(sizeof(data_) == bytes, "");
100 
103  using value_type = unsigned char;
104  using pointer = value_type*;
106  using const_pointer = value_type const*;
107  using const_reference = value_type const&;
108  using iterator = pointer;
112  using tag_type = Tag;
113 
114  pointer
116  {
117  return reinterpret_cast<pointer>(data_.data());
118  }
120  data() const
121  {
122  return reinterpret_cast<const_pointer>(data_.data());
123  }
124 
125  iterator
127  {
128  return data();
129  }
130  iterator
131  end()
132  {
133  return data() + bytes;
134  }
136  begin() const
137  {
138  return data();
139  }
141  end() const
142  {
143  return data() + bytes;
144  }
146  cbegin() const
147  {
148  return data();
149  }
151  cend() const
152  {
153  return data() + bytes;
154  }
155 
161 
162  //--------------------------------------------------------------------------
163 
164 private:
171  // NIKB TODO Remove the need for this constructor.
172  struct VoidHelper
173  {
174  explicit VoidHelper() = default;
175  };
176 
177  explicit base_uint(void const* data, VoidHelper)
178  {
179  memcpy(data_.data(), data, bytes);
180  }
181 
182  // Helper function to initialize a base_uint from a std::string_view.
183  enum class ParseResult {
184  okay,
185  badLength,
186  badChar,
187  };
188 
189  constexpr Expected<decltype(data_), ParseResult>
191  {
192  // Local lambda that converts a single hex char to four bits and
193  // ORs those bits into a uint32_t.
194  auto hexCharToUInt = [](char c,
195  std::uint32_t shift,
196  std::uint32_t& accum) -> ParseResult {
197  std::uint32_t nibble = 0xFFu;
198  if (c < '0' || c > 'f')
199  return ParseResult::badChar;
200 
201  if (c >= 'a')
202  nibble = static_cast<std::uint32_t>(c - 'a' + 0xA);
203  else if (c >= 'A')
204  nibble = static_cast<std::uint32_t>(c - 'A' + 0xA);
205  else if (c <= '9')
206  nibble = static_cast<std::uint32_t>(c - '0');
207 
208  if (nibble > 0xFu)
209  return ParseResult::badChar;
210 
211  accum |= (nibble << shift);
212 
213  return ParseResult::okay;
214  };
215 
216  decltype(data_) ret{};
217 
218  if (sv == "0")
219  {
220  return ret;
221  }
222 
223  if (sv.size() != size() * 2)
225 
226  std::size_t i = 0u;
227  auto in = sv.begin();
228  while (in != sv.end())
229  {
230  std::uint32_t accum = {};
231  for (std::uint32_t shift : {4u, 0u, 12u, 8u, 20u, 16u, 28u, 24u})
232  {
233  if (auto const result = hexCharToUInt(*in++, shift, accum);
234  result != ParseResult::okay)
235  return Unexpected(result);
236  }
237  ret[i++] = accum;
238  }
239  return ret;
240  }
241 
242  constexpr decltype(data_)
243  parseFromStringViewThrows(std::string_view sv) noexcept(false)
244  {
245  auto const result = parseFromStringView(sv);
246  if (!result)
247  {
248  if (result.error() == ParseResult::badLength)
249  Throw<std::invalid_argument>("invalid length for hex string");
250 
251  Throw<std::range_error>("invalid hex character");
252  }
253  return *result;
254  }
255 
256 public:
257  constexpr base_uint() : data_{}
258  {
259  }
260 
261  constexpr base_uint(beast::Zero) : data_{}
262  {
263  }
264 
266  {
267  *this = b;
268  }
269 
270  // This constructor is intended to be used at compile time since it might
271  // throw at runtime. Consider declaring this constructor consteval once
272  // we get to C++23.
273  explicit constexpr base_uint(std::string_view sv) noexcept(false)
275  {
276  }
277 
278  template <
279  class Container,
280  class = std::enable_if_t<
283  explicit base_uint(Container const& c)
284  {
285  assert(c.size() * sizeof(typename Container::value_type) == size());
286  std::memcpy(data_.data(), c.data(), size());
287  }
288 
289  template <class Container>
293  base_uint&>
294  operator=(Container const& c)
295  {
296  assert(c.size() * sizeof(typename Container::value_type) == size());
297  std::memcpy(data_.data(), c.data(), size());
298  return *this;
299  }
300 
301  /* Construct from a raw pointer.
302  The buffer pointed to by `data` must be at least Bits/8 bytes.
303  */
304  static base_uint
305  fromVoid(void const* data)
306  {
307  return base_uint(data, VoidHelper());
308  }
309 
310  template <class T>
312  fromVoidChecked(T const& from)
313  {
314  if (from.size() != size())
315  return {};
316  return fromVoid(from.data());
317  }
318 
319  constexpr int
320  signum() const
321  {
322  for (int i = 0; i < WIDTH; i++)
323  if (data_[i] != 0)
324  return 1;
325 
326  return 0;
327  }
328 
329  bool
330  operator!() const
331  {
332  return *this == beast::zero;
333  }
334 
335  const base_uint
336  operator~() const
337  {
338  base_uint ret;
339 
340  for (int i = 0; i < WIDTH; i++)
341  ret.data_[i] = ~data_[i];
342 
343  return ret;
344  }
345 
346  base_uint&
348  {
349  *this = beast::zero;
350  union
351  {
352  unsigned u[2];
353  std::uint64_t ul;
354  };
355  // Put in least significant bits.
356  ul = boost::endian::native_to_big(uHost);
357  data_[WIDTH - 2] = u[0];
358  data_[WIDTH - 1] = u[1];
359  return *this;
360  }
361 
362  base_uint&
364  {
365  for (int i = 0; i < WIDTH; i++)
366  data_[i] ^= b.data_[i];
367 
368  return *this;
369  }
370 
371  base_uint&
373  {
374  for (int i = 0; i < WIDTH; i++)
375  data_[i] &= b.data_[i];
376 
377  return *this;
378  }
379 
380  base_uint&
382  {
383  for (int i = 0; i < WIDTH; i++)
384  data_[i] |= b.data_[i];
385 
386  return *this;
387  }
388 
389  base_uint&
391  {
392  // prefix operator
393  for (int i = WIDTH - 1; i >= 0; --i)
394  {
395  data_[i] = boost::endian::native_to_big(
396  boost::endian::big_to_native(data_[i]) + 1);
397  if (data_[i] != 0)
398  break;
399  }
400 
401  return *this;
402  }
403 
404  const base_uint
406  {
407  // postfix operator
408  const base_uint ret = *this;
409  ++(*this);
410 
411  return ret;
412  }
413 
414  base_uint&
416  {
417  for (int i = WIDTH - 1; i >= 0; --i)
418  {
419  auto prev = data_[i];
420  data_[i] = boost::endian::native_to_big(
421  boost::endian::big_to_native(data_[i]) - 1);
422 
423  if (prev != 0)
424  break;
425  }
426 
427  return *this;
428  }
429 
430  const base_uint
432  {
433  // postfix operator
434  const base_uint ret = *this;
435  --(*this);
436 
437  return ret;
438  }
439 
440  base_uint&
442  {
443  std::uint64_t carry = 0;
444 
445  for (int i = WIDTH; i--;)
446  {
447  std::uint64_t n = carry + boost::endian::big_to_native(data_[i]) +
448  boost::endian::big_to_native(b.data_[i]);
449 
450  data_[i] =
451  boost::endian::native_to_big(static_cast<std::uint32_t>(n));
452  carry = n >> 32;
453  }
454 
455  return *this;
456  }
457 
458  template <class Hasher>
459  friend void
460  hash_append(Hasher& h, base_uint const& a) noexcept
461  {
462  // Do not allow any endian transformations on this memory
463  h(a.data_.data(), sizeof(a.data_));
464  }
465 
474  [[nodiscard]] constexpr bool
476  {
477  auto const result = parseFromStringView(sv);
478  if (!result)
479  return false;
480 
481  data_ = *result;
482  return true;
483  }
484 
485  [[nodiscard]] constexpr bool
486  parseHex(const char* str)
487  {
488  return parseHex(std::string_view{str});
489  }
490 
491  [[nodiscard]] bool
492  parseHex(std::string const& str)
493  {
494  return parseHex(std::string_view{str});
495  }
496 
497  constexpr static std::size_t
499  {
500  return bytes;
501  }
502 
504  {
505  data_.fill(0);
506  return *this;
507  }
508 
509  // Deprecated.
510  bool
511  isZero() const
512  {
513  return *this == beast::zero;
514  }
515  bool
516  isNonZero() const
517  {
518  return *this != beast::zero;
519  }
520  void
522  {
523  *this = beast::zero;
524  }
525 };
526 
530 
531 template <std::size_t Bits, class Tag>
532 inline int
534 {
535  auto ret = std::mismatch(a.cbegin(), a.cend(), b.cbegin());
536 
537  if (ret.first == a.cend())
538  return 0;
539 
540  // a > b
541  if (*ret.first > *ret.second)
542  return 1;
543 
544  // a < b
545  return -1;
546 }
547 
548 template <std::size_t Bits, class Tag>
549 inline bool
551 {
552  return compare(a, b) < 0;
553 }
554 
555 template <std::size_t Bits, class Tag>
556 inline bool
558 {
559  return compare(a, b) <= 0;
560 }
561 
562 template <std::size_t Bits, class Tag>
563 inline bool
565 {
566  return compare(a, b) > 0;
567 }
568 
569 template <std::size_t Bits, class Tag>
570 inline bool
572 {
573  return compare(a, b) >= 0;
574 }
575 
576 template <std::size_t Bits, class Tag>
577 inline bool
579 {
580  return compare(a, b) == 0;
581 }
582 
583 template <std::size_t Bits, class Tag>
584 inline bool
586 {
587  return compare(a, b) != 0;
588 }
589 
590 //------------------------------------------------------------------------------
591 template <std::size_t Bits, class Tag>
592 inline bool
594 {
595  return a == base_uint<Bits, Tag>(b);
596 }
597 
598 template <std::size_t Bits, class Tag>
599 inline bool
601 {
602  return !(a == b);
603 }
604 
605 //------------------------------------------------------------------------------
606 template <std::size_t Bits, class Tag>
607 inline const base_uint<Bits, Tag>
609 {
610  return base_uint<Bits, Tag>(a) ^= b;
611 }
612 
613 template <std::size_t Bits, class Tag>
614 inline const base_uint<Bits, Tag>
616 {
617  return base_uint<Bits, Tag>(a) &= b;
618 }
619 
620 template <std::size_t Bits, class Tag>
621 inline const base_uint<Bits, Tag>
623 {
624  return base_uint<Bits, Tag>(a) |= b;
625 }
626 
627 template <std::size_t Bits, class Tag>
628 inline const base_uint<Bits, Tag>
630 {
631  return base_uint<Bits, Tag>(a) += b;
632 }
633 
634 //------------------------------------------------------------------------------
635 template <std::size_t Bits, class Tag>
636 inline std::string
638 {
639  return strHex(a.cbegin(), a.cend());
640 }
641 
642 template <std::size_t Bits, class Tag>
643 inline std::ostream&
645 {
646  return out << to_string(u);
647 }
648 
649 #ifndef __INTELLISENSE__
650 static_assert(sizeof(uint128) == 128 / 8, "There should be no padding bytes");
651 static_assert(sizeof(uint160) == 160 / 8, "There should be no padding bytes");
652 static_assert(sizeof(uint256) == 256 / 8, "There should be no padding bytes");
653 #endif
654 
655 } // namespace ripple
656 
657 namespace beast {
658 
659 template <std::size_t Bits, class Tag>
660 struct is_uniquely_represented<ripple::base_uint<Bits, Tag>>
661  : public std::true_type
662 {
663  explicit is_uniquely_represented() = default;
664 };
665 
666 } // namespace beast
667 
668 #endif
ripple::operator>
bool operator>(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:564
ripple::base_uint< 256 >::iterator
pointer iterator
Definition: base_uint.h:108
std::false_type
ripple::base_uint::operator--
base_uint & operator--()
Definition: base_uint.h:415
ripple::operator|
const base_uint< Bits, Tag > operator|(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:622
ripple::Dir::const_iterator
Definition: Directory.h:49
ripple::base_uint::operator--
const base_uint operator--(int)
Definition: base_uint.h:431
std::string
STL class.
ripple::base_uint::hash_append
friend void hash_append(Hasher &h, base_uint const &a) noexcept
Definition: base_uint.h:460
ripple::uint160
base_uint< 160 > uint160
Definition: base_uint.h:528
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:516
cstring
ripple::base_uint::ParseResult::badLength
@ badLength
ripple::base_uint< 256 >::value_type
unsigned char value_type
Definition: base_uint.h:103
std::string_view
STL class.
ripple::base_uint::VoidHelper
Construct from a raw pointer.
Definition: base_uint.h:172
functional
ripple::base_uint::ParseResult::badChar
@ badChar
ripple::operator>=
bool operator>=(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:571
ripple::base_uint::base_uint
base_uint(Container const &c)
Definition: base_uint.h:283
ripple::base_uint::end
iterator end()
Definition: base_uint.h:131
ripple::base_uint::data
const_pointer data() const
Definition: base_uint.h:120
ripple::Unexpected
Unexpected(E(&)[N]) -> Unexpected< E const * >
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:294
ripple::QualityDirection::in
@ in
ripple::base_uint::cbegin
const_iterator cbegin() const
Definition: base_uint.h:146
ripple::base_uint< 256 >::pointer
value_type * pointer
Definition: base_uint.h:104
ripple::base_uint::WIDTH
static constexpr std::size_t WIDTH
Definition: base_uint.h:85
ripple::base_uint< 256 >::ParseResult
ParseResult
Definition: base_uint.h:183
ripple::base_uint::fromVoidChecked
static std::optional< base_uint > fromVoidChecked(T const &from)
Definition: base_uint.h:312
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:115
ripple::operator==
bool operator==(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:159
std::array::fill
T fill(T... args)
ripple::base_uint::size
constexpr static std::size_t size()
Definition: base_uint.h:498
ripple::base_uint< 256 >::const_iterator
const_pointer const_iterator
Definition: base_uint.h:109
ripple::base_uint::parseFromStringView
constexpr Expected< decltype(data_), ParseResult > parseFromStringView(std::string_view sv) noexcept
Definition: base_uint.h:190
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:529
beast::is_uniquely_represented
Definition: hash_append.h:95
ripple::base_uint::operator~
const base_uint operator~() const
Definition: base_uint.h:336
ripple::base_uint::parseHex
bool parseHex(std::string const &str)
Definition: base_uint.h:492
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:75
ripple::base_uint< 256 >::const_reference
value_type const & const_reference
Definition: base_uint.h:107
ripple::operator<=
bool operator<=(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:557
ripple::base_uint::operator|=
base_uint & operator|=(const base_uint &b)
Definition: base_uint.h:381
ripple::base_uint::VoidHelper::VoidHelper
VoidHelper()=default
ripple::QualityDirection::out
@ out
ripple::Expected
Definition: Expected.h:129
ripple::operator+
const base_uint< Bits, Tag > operator+(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:629
ripple::base_uint::bytes
static constexpr std::size_t bytes
Definition: base_uint.h:98
ripple::base_uint::data_
std::array< std::uint32_t, WIDTH > data_
Definition: base_uint.h:90
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:511
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:533
ripple::base_uint::operator&=
base_uint & operator&=(const base_uint &b)
Definition: base_uint.h:372
ripple::base_uint::begin
const_iterator begin() const
Definition: base_uint.h:136
ripple::operator!=
bool operator!=(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:169
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::uint32_t
ripple::base_uint::signum
constexpr int signum() const
Definition: base_uint.h:320
ripple::base_uint::base_uint
constexpr base_uint(beast::Zero)
Definition: base_uint.h:261
ripple::operator^
const base_uint< Bits, Tag > operator^(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:608
ripple::uint128
base_uint< 128 > uint128
Definition: base_uint.h:527
ripple::operator&
const base_uint< Bits, Tag > operator&(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:615
ripple::base_uint< 256 >::tag_type
void tag_type
Definition: base_uint.h:112
ripple::base_uint::ParseResult::okay
@ okay
ripple::base_uint::operator++
base_uint & operator++()
Definition: base_uint.h:390
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:45
ripple::base_uint::parseHex
constexpr bool parseHex(const char *str)
Definition: base_uint.h:486
ripple::base_uint::begin
iterator begin()
Definition: base_uint.h:126
ripple::base_uint::base_uint
base_uint(void const *data, VoidHelper)
Definition: base_uint.h:177
ripple::base_uint::parseFromStringViewThrows
constexpr decltype(data_) parseFromStringViewThrows(std::string_view sv) noexcept(false)
Definition: base_uint.h:243
ripple::base_uint::operator=
base_uint< Bits, Tag > & operator=(beast::Zero)
Definition: base_uint.h:503
ripple::base_uint::zero
void zero()
Definition: base_uint.h:521
ripple::base_uint::base_uint
base_uint(std::uint64_t b)
Definition: base_uint.h:265
std
STL namespace.
ripple::base_uint::fromVoid
static base_uint fromVoid(void const *data)
Definition: base_uint.h:305
ripple::base_uint::end
const_iterator end() const
Definition: base_uint.h:141
std::ptrdiff_t
std::optional
std::size_t
ripple::base_uint::operator^=
base_uint & operator^=(const base_uint &b)
Definition: base_uint.h:363
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:38
std::memcpy
T memcpy(T... args)
ripple::base_uint::operator++
const base_uint operator++(int)
Definition: base_uint.h:405
ripple::base_uint::cend
const_iterator cend() const
Definition: base_uint.h:151
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:45
std::reverse_iterator
ripple::base_uint::operator=
base_uint & operator=(std::uint64_t uHost)
Definition: base_uint.h:347
ripple::base_uint::operator+=
base_uint & operator+=(const base_uint &b)
Definition: base_uint.h:441
ripple::base_uint::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:475
ripple::base_uint::operator!
bool operator!() const
Definition: base_uint.h:330
ripple::base_uint< 256 >::const_pointer
value_type const * const_pointer
Definition: base_uint.h:106
ripple::base_uint< 256 >::reference
value_type & reference
Definition: base_uint.h:105
ripple::base_uint::base_uint
constexpr base_uint()
Definition: base_uint.h:257
std::array::data
T data(T... args)
type_traits
ripple::base_uint::base_uint
constexpr base_uint(std::string_view sv) noexcept(false)
Definition: base_uint.h:273
beast
Definition: base_uint.h:657