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/cxx17/type_traits.h>
31 #include <ripple/beast/utility/Zero.h>
32 #include <boost/endian/conversion.hpp>
33 #include <boost/functional/hash.hpp>
34 #include <array>
35 #include <cstring>
36 #include <functional>
37 #include <type_traits>
38 
39 namespace ripple {
40 
41 namespace detail {
42 
43 template <class Container, class = std::void_t<>>
45 {
46 };
47 
48 template <class Container>
50  Container,
51  std::void_t<
52  decltype(std::declval<Container const>().size()),
53  decltype(std::declval<Container const>().data()),
54  typename Container::value_type>> : std::true_type
55 {
56 };
57 
58 } // namespace detail
59 
60 // This class stores its values internally in big-endian form
61 
62 template <std::size_t Bits, class Tag = void>
63 class base_uint
64 {
65  static_assert(
66  (Bits % 32) == 0,
67  "The length of a base_uint in bits must be a multiple of 32.");
68 
69  static_assert(
70  Bits >= 64,
71  "The length of a base_uint in bits must be at least 64.");
72 
73  static constexpr std::size_t WIDTH = Bits / 32;
74 
75  // This is really big-endian in byte order.
76  // We sometimes use std::uint32_t for speed.
77 
79 
80 public:
81  //--------------------------------------------------------------------------
82  //
83  // STL Container Interface
84  //
85 
86  static std::size_t constexpr bytes = Bits / 8;
87  static_assert(sizeof(data_) == bytes, "");
88 
91  using value_type = unsigned char;
92  using pointer = value_type*;
94  using const_pointer = value_type const*;
95  using const_reference = value_type const&;
96  using iterator = pointer;
100  using tag_type = Tag;
101 
102  pointer
104  {
105  return reinterpret_cast<pointer>(data_.data());
106  }
108  data() const
109  {
110  return reinterpret_cast<const_pointer>(data_.data());
111  }
112 
113  iterator
115  {
116  return data();
117  }
118  iterator
119  end()
120  {
121  return data() + bytes;
122  }
124  begin() const
125  {
126  return data();
127  }
129  end() const
130  {
131  return data() + bytes;
132  }
134  cbegin() const
135  {
136  return data();
137  }
139  cend() const
140  {
141  return data() + bytes;
142  }
143 
149 
150  //--------------------------------------------------------------------------
151 
152 private:
159  // NIKB TODO Remove the need for this constructor.
160  struct VoidHelper
161  {
162  explicit VoidHelper() = default;
163  };
164 
165  explicit base_uint(void const* data, VoidHelper)
166  {
167  memcpy(data_.data(), data, bytes);
168  }
169 
170 public:
172  {
173  *this = beast::zero;
174  }
175 
177  {
178  *this = beast::zero;
179  }
180 
182  {
183  *this = b;
184  }
185 
186  template <
187  class Container,
188  class = std::enable_if_t<
191  explicit base_uint(Container const& c)
192  {
193  assert(c.size() * sizeof(typename Container::value_type) == size());
194  std::memcpy(data_.data(), c.data(), size());
195  }
196 
197  template <class Container>
201  base_uint&>
202  operator=(Container const& c)
203  {
204  assert(c.size() * sizeof(typename Container::value_type) == size());
205  std::memcpy(data_.data(), c.data(), size());
206  return *this;
207  }
208 
209  /* Construct from a raw pointer.
210  The buffer pointed to by `data` must be at least Bits/8 bytes.
211  */
212  static base_uint
213  fromVoid(void const* data)
214  {
215  return base_uint(data, VoidHelper());
216  }
217 
218  int
219  signum() const
220  {
221  for (int i = 0; i < WIDTH; i++)
222  if (data_[i] != 0)
223  return 1;
224 
225  return 0;
226  }
227 
228  bool
229  operator!() const
230  {
231  return *this == beast::zero;
232  }
233 
234  const base_uint
235  operator~() const
236  {
237  base_uint ret;
238 
239  for (int i = 0; i < WIDTH; i++)
240  ret.data_[i] = ~data_[i];
241 
242  return ret;
243  }
244 
245  base_uint&
247  {
248  *this = beast::zero;
249  union
250  {
251  unsigned u[2];
252  std::uint64_t ul;
253  };
254  // Put in least significant bits.
255  ul = boost::endian::native_to_big(uHost);
256  data_[WIDTH - 2] = u[0];
257  data_[WIDTH - 1] = u[1];
258  return *this;
259  }
260 
261  base_uint&
263  {
264  for (int i = 0; i < WIDTH; i++)
265  data_[i] ^= b.data_[i];
266 
267  return *this;
268  }
269 
270  base_uint&
272  {
273  for (int i = 0; i < WIDTH; i++)
274  data_[i] &= b.data_[i];
275 
276  return *this;
277  }
278 
279  base_uint&
281  {
282  for (int i = 0; i < WIDTH; i++)
283  data_[i] |= b.data_[i];
284 
285  return *this;
286  }
287 
288  base_uint&
290  {
291  // prefix operator
292  for (int i = WIDTH - 1; i >= 0; --i)
293  {
294  data_[i] = boost::endian::native_to_big(
295  boost::endian::big_to_native(data_[i]) + 1);
296  if (data_[i] != 0)
297  break;
298  }
299 
300  return *this;
301  }
302 
303  const base_uint
305  {
306  // postfix operator
307  const base_uint ret = *this;
308  ++(*this);
309 
310  return ret;
311  }
312 
313  base_uint&
315  {
316  for (int i = WIDTH - 1; i >= 0; --i)
317  {
318  auto prev = data_[i];
319  data_[i] = boost::endian::native_to_big(
320  boost::endian::big_to_native(data_[i]) - 1);
321 
322  if (prev != 0)
323  break;
324  }
325 
326  return *this;
327  }
328 
329  const base_uint
331  {
332  // postfix operator
333  const base_uint ret = *this;
334  --(*this);
335 
336  return ret;
337  }
338 
339  base_uint&
341  {
342  std::uint64_t carry = 0;
343 
344  for (int i = WIDTH; i--;)
345  {
346  std::uint64_t n = carry + boost::endian::big_to_native(data_[i]) +
347  boost::endian::big_to_native(b.data_[i]);
348 
349  data_[i] =
350  boost::endian::native_to_big(static_cast<std::uint32_t>(n));
351  carry = n >> 32;
352  }
353 
354  return *this;
355  }
356 
357  template <class Hasher>
358  friend void
359  hash_append(Hasher& h, base_uint const& a) noexcept
360  {
361  // Do not allow any endian transformations on this memory
362  h(a.data_.data(), sizeof(a.data_));
363  }
364 
369  bool
370  SetHexExact(const char* psz)
371  {
372  unsigned char* pOut = begin();
373 
374  for (int i = 0; i < sizeof(data_); ++i)
375  {
376  auto hi = charUnHex(*psz++);
377  if (hi == -1)
378  return false;
379 
380  auto lo = charUnHex(*psz++);
381  if (lo == -1)
382  return false;
383 
384  *pOut++ = (hi << 4) | lo;
385  }
386 
387  // We've consumed exactly as many bytes as we needed at this point
388  // so we should be at the end of the string.
389  return (*psz == 0);
390  }
391 
405  bool
406  SetHex(const char* psz, bool bStrict = false)
407  {
408  // Find beginning.
409  auto pBegin = reinterpret_cast<const unsigned char*>(psz);
410  // skip leading spaces
411  if (!bStrict)
412  while (isspace(*pBegin))
413  pBegin++;
414 
415  // skip 0x
416  if (!bStrict && pBegin[0] == '0' && tolower(pBegin[1]) == 'x')
417  pBegin += 2;
418 
419  // Find end.
420  auto pEnd = pBegin;
421  while (charUnHex(*pEnd) != -1)
422  pEnd++;
423 
424  // Take only last digits of over long string.
425  if ((unsigned int)(pEnd - pBegin) > 2 * size())
426  pBegin = pEnd - 2 * size();
427 
428  unsigned char* pOut = end() - ((pEnd - pBegin + 1) / 2);
429 
430  *this = beast::zero;
431 
432  if ((pEnd - pBegin) & 1)
433  *pOut++ = charUnHex(*pBegin++);
434 
435  while (pBegin != pEnd)
436  {
437  auto cHigh = charUnHex(*pBegin++);
438  auto cLow = pBegin == pEnd ? 0 : charUnHex(*pBegin++);
439 
440  if (cHigh == -1 || cLow == -1)
441  return false;
442 
443  *pOut++ = (cHigh << 4) | cLow;
444  }
445 
446  return !*pEnd;
447  }
448 
449  bool
450  SetHex(std::string const& str, bool bStrict = false)
451  {
452  return SetHex(str.c_str(), bStrict);
453  }
454 
455  bool
457  {
458  return SetHexExact(str.c_str());
459  }
460 
461  constexpr static std::size_t
463  {
464  return bytes;
465  }
466 
468  {
469  data_.fill(0);
470  return *this;
471  }
472 
473  // Deprecated.
474  bool
475  isZero() const
476  {
477  return *this == beast::zero;
478  }
479  bool
480  isNonZero() const
481  {
482  return *this != beast::zero;
483  }
484  void
486  {
487  *this = beast::zero;
488  }
489 };
490 
494 
495 template <std::size_t Bits, class Tag>
496 inline int
498 {
499  auto ret = std::mismatch(a.cbegin(), a.cend(), b.cbegin());
500 
501  if (ret.first == a.cend())
502  return 0;
503 
504  // a > b
505  if (*ret.first > *ret.second)
506  return 1;
507 
508  // a < b
509  return -1;
510 }
511 
512 template <std::size_t Bits, class Tag>
513 inline bool
515 {
516  return compare(a, b) < 0;
517 }
518 
519 template <std::size_t Bits, class Tag>
520 inline bool
522 {
523  return compare(a, b) <= 0;
524 }
525 
526 template <std::size_t Bits, class Tag>
527 inline bool
529 {
530  return compare(a, b) > 0;
531 }
532 
533 template <std::size_t Bits, class Tag>
534 inline bool
536 {
537  return compare(a, b) >= 0;
538 }
539 
540 template <std::size_t Bits, class Tag>
541 inline bool
543 {
544  return compare(a, b) == 0;
545 }
546 
547 template <std::size_t Bits, class Tag>
548 inline bool
550 {
551  return compare(a, b) != 0;
552 }
553 
554 //------------------------------------------------------------------------------
555 template <std::size_t Bits, class Tag>
556 inline bool
558 {
559  return a == base_uint<Bits, Tag>(b);
560 }
561 
562 template <std::size_t Bits, class Tag>
563 inline bool
565 {
566  return !(a == b);
567 }
568 
569 //------------------------------------------------------------------------------
570 template <std::size_t Bits, class Tag>
571 inline const base_uint<Bits, Tag>
573 {
574  return base_uint<Bits, Tag>(a) ^= b;
575 }
576 
577 template <std::size_t Bits, class Tag>
578 inline const base_uint<Bits, Tag>
580 {
581  return base_uint<Bits, Tag>(a) &= b;
582 }
583 
584 template <std::size_t Bits, class Tag>
585 inline const base_uint<Bits, Tag>
587 {
588  return base_uint<Bits, Tag>(a) |= b;
589 }
590 
591 template <std::size_t Bits, class Tag>
592 inline const base_uint<Bits, Tag>
594 {
595  return base_uint<Bits, Tag>(a) += b;
596 }
597 
598 //------------------------------------------------------------------------------
599 template <std::size_t Bits, class Tag>
600 inline std::string
602 {
603  return strHex(a.cbegin(), a.cend());
604 }
605 
606 // Function templates that return a base_uint given text in hexadecimal.
607 // Invoke like:
608 // auto i = from_hex_text<uint256>("AAAAA");
609 template <typename T>
610 auto
611 from_hex_text(char const* text) -> std::enable_if_t<
613  T>
614 {
615  T ret;
616  ret.SetHex(text);
617  return ret;
618 }
619 
620 template <typename T>
621 auto
624  T>
625 {
626  T ret;
627  ret.SetHex(text);
628  return ret;
629 }
630 
631 template <std::size_t Bits, class Tag>
632 inline std::ostream&
634 {
635  return out << to_string(u);
636 }
637 
638 #ifndef __INTELLISENSE__
639 static_assert(sizeof(uint128) == 128 / 8, "There should be no padding bytes");
640 static_assert(sizeof(uint160) == 160 / 8, "There should be no padding bytes");
641 static_assert(sizeof(uint256) == 256 / 8, "There should be no padding bytes");
642 #endif
643 
644 } // namespace ripple
645 
646 namespace beast {
647 
648 template <std::size_t Bits, class Tag>
649 struct is_uniquely_represented<ripple::base_uint<Bits, Tag>>
650  : public std::true_type
651 {
652  explicit is_uniquely_represented() = default;
653 };
654 
655 } // namespace beast
656 
657 #endif
ripple::base_uint::signum
int signum() const
Definition: base_uint.h:219
std::is_same
ripple::operator>
bool operator>(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:528
ripple::base_uint< 256 >::iterator
pointer iterator
Definition: base_uint.h:96
std::false_type
ripple::base_uint::operator--
base_uint & operator--()
Definition: base_uint.h:314
ripple::operator|
const base_uint< Bits, Tag > operator|(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:586
ripple::Dir::const_iterator
Definition: Directory.h:49
ripple::base_uint::operator--
const base_uint operator--(int)
Definition: base_uint.h:330
std::string
STL class.
ripple::base_uint::hash_append
friend void hash_append(Hasher &h, base_uint const &a) noexcept
Definition: base_uint.h:359
ripple::uint160
base_uint< 160 > uint160
Definition: base_uint.h:492
ripple::charUnHex
int charUnHex(unsigned char c)
Converts a hex digit to the corresponding integer.
Definition: strHex.cpp:27
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:480
cstring
ripple::base_uint< 256 >::value_type
unsigned char value_type
Definition: base_uint.h:91
ripple::base_uint::VoidHelper
Construct from a raw pointer.
Definition: base_uint.h:160
functional
ripple::operator>=
bool operator>=(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:535
ripple::base_uint::base_uint
base_uint(Container const &c)
Definition: base_uint.h:191
ripple::base_uint::end
iterator end()
Definition: base_uint.h:119
ripple::base_uint::data
const_pointer data() const
Definition: base_uint.h:108
ripple::base_uint::SetHexExact
bool SetHexExact(std::string const &str)
Definition: base_uint.h:456
ripple::base_uint::SetHex
bool SetHex(std::string const &str, bool bStrict=false)
Definition: base_uint.h:450
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:202
ripple::from_hex_text
auto from_hex_text(char const *text) -> std::enable_if_t< std::is_same< T, base_uint< T::bytes *8, typename T::tag_type >>::value, T >
Definition: base_uint.h:611
ripple::base_uint::cbegin
const_iterator cbegin() const
Definition: base_uint.h:134
ripple::base_uint< 256 >::pointer
value_type * pointer
Definition: base_uint.h:92
ripple::base_uint::WIDTH
static constexpr std::size_t WIDTH
Definition: base_uint.h:73
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:42
ripple::base_uint::base_uint
base_uint(beast::Zero)
Definition: base_uint.h:176
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:103
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:462
ripple::base_uint< 256 >::const_iterator
const_pointer const_iterator
Definition: base_uint.h:97
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:493
beast::is_uniquely_represented
Definition: hash_append.h:93
ripple::base_uint::operator~
const base_uint operator~() const
Definition: base_uint.h:235
beast::is_uniquely_represented::is_uniquely_represented
is_uniquely_represented()=default
std::mismatch
T mismatch(T... args)
ripple::base_uint
Definition: base_uint.h:63
ripple::base_uint< 256 >::const_reference
value_type const & const_reference
Definition: base_uint.h:95
ripple::operator<=
bool operator<=(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:521
ripple::base_uint::operator|=
base_uint & operator|=(const base_uint &b)
Definition: base_uint.h:280
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:593
ripple::base_uint::bytes
static constexpr std::size_t bytes
Definition: base_uint.h:86
ripple::base_uint::data_
std::array< std::uint32_t, WIDTH > data_
Definition: base_uint.h:78
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:475
std::is_trivially_copyable
std::enable_if_t
std::ostream
STL class.
ripple::compare
int compare(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:497
ripple::base_uint::operator&=
base_uint & operator&=(const base_uint &b)
Definition: base_uint.h:271
ripple::base_uint::begin
const_iterator begin() const
Definition: base_uint.h:124
std::string::c_str
T c_str(T... args)
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::base_uint::SetHex
bool SetHex(const char *psz, bool bStrict=false)
Parse a hex string into a base_uint The input can be:
Definition: base_uint.h:406
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:572
ripple::uint128
base_uint< 128 > uint128
Definition: base_uint.h:491
ripple::operator&
const base_uint< Bits, Tag > operator&(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:579
ripple::base_uint::SetHexExact
bool SetHexExact(const char *psz)
Parse a hex string into a base_uint The string must contain exactly bytes * 2 hex characters and must...
Definition: base_uint.h:370
ripple::base_uint< 256 >::tag_type
void tag_type
Definition: base_uint.h:100
ripple::base_uint::operator++
base_uint & operator++()
Definition: base_uint.h:289
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:44
ripple::base_uint::begin
iterator begin()
Definition: base_uint.h:114
ripple::base_uint::base_uint
base_uint(void const *data, VoidHelper)
Definition: base_uint.h:165
ripple::base_uint::operator=
base_uint< Bits, Tag > & operator=(beast::Zero)
Definition: base_uint.h:467
ripple::base_uint::zero
void zero()
Definition: base_uint.h:485
ripple::base_uint::base_uint
base_uint(std::uint64_t b)
Definition: base_uint.h:181
std
STL namespace.
ripple::base_uint::fromVoid
static base_uint fromVoid(void const *data)
Definition: base_uint.h:213
ripple::base_uint::end
const_iterator end() const
Definition: base_uint.h:129
std::ptrdiff_t
std::size_t
ripple::base_uint::operator^=
base_uint & operator^=(const base_uint &b)
Definition: base_uint.h:262
std::memcpy
T memcpy(T... args)
ripple::base_uint::operator++
const base_uint operator++(int)
Definition: base_uint.h:304
ripple::base_uint::cend
const_iterator cend() const
Definition: base_uint.h:139
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:67
std::reverse_iterator
ripple::base_uint::operator=
base_uint & operator=(std::uint64_t uHost)
Definition: base_uint.h:246
ripple::base_uint::operator+=
base_uint & operator+=(const base_uint &b)
Definition: base_uint.h:340
ripple::operator<
bool operator<(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:514
ripple::base_uint::operator!
bool operator!() const
Definition: base_uint.h:229
ripple::base_uint< 256 >::const_pointer
value_type const * const_pointer
Definition: base_uint.h:94
ripple::base_uint< 256 >::reference
value_type & reference
Definition: base_uint.h:93
std::array::data
T data(T... args)
type_traits
ripple::base_uint::base_uint
base_uint()
Definition: base_uint.h:171
beast
Definition: base_uint.h:646