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