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  constexpr 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
441  next() const
442  {
443  auto ret = *this;
444  return ++ret;
445  }
446 
447  base_uint
448  prev() const
449  {
450  auto ret = *this;
451  return --ret;
452  }
453 
454  base_uint&
456  {
457  std::uint64_t carry = 0;
458 
459  for (int i = WIDTH; i--;)
460  {
461  std::uint64_t n = carry + boost::endian::big_to_native(data_[i]) +
462  boost::endian::big_to_native(b.data_[i]);
463 
464  data_[i] =
465  boost::endian::native_to_big(static_cast<std::uint32_t>(n));
466  carry = n >> 32;
467  }
468 
469  return *this;
470  }
471 
472  template <class Hasher>
473  friend void
474  hash_append(Hasher& h, base_uint const& a) noexcept
475  {
476  // Do not allow any endian transformations on this memory
477  h(a.data_.data(), sizeof(a.data_));
478  }
479 
488  [[nodiscard]] constexpr bool
490  {
491  auto const result = parseFromStringView(sv);
492  if (!result)
493  return false;
494 
495  data_ = *result;
496  return true;
497  }
498 
499  [[nodiscard]] constexpr bool
500  parseHex(const char* str)
501  {
502  return parseHex(std::string_view{str});
503  }
504 
505  [[nodiscard]] bool
506  parseHex(std::string const& str)
507  {
508  return parseHex(std::string_view{str});
509  }
510 
511  constexpr static std::size_t
513  {
514  return bytes;
515  }
516 
518  {
519  data_.fill(0);
520  return *this;
521  }
522 
523  // Deprecated.
524  bool
525  isZero() const
526  {
527  return *this == beast::zero;
528  }
529  bool
530  isNonZero() const
531  {
532  return *this != beast::zero;
533  }
534  void
536  {
537  *this = beast::zero;
538  }
539 };
540 
544 
545 template <std::size_t Bits, class Tag>
546 inline int
548 {
549  auto ret = std::mismatch(a.cbegin(), a.cend(), b.cbegin());
550 
551  if (ret.first == a.cend())
552  return 0;
553 
554  // a > b
555  if (*ret.first > *ret.second)
556  return 1;
557 
558  // a < b
559  return -1;
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 template <std::size_t Bits, class Tag>
591 inline bool
593 {
594  return compare(a, b) == 0;
595 }
596 
597 template <std::size_t Bits, class Tag>
598 inline bool
600 {
601  return compare(a, b) != 0;
602 }
603 
604 //------------------------------------------------------------------------------
605 template <std::size_t Bits, class Tag>
606 inline bool
608 {
609  return a == base_uint<Bits, Tag>(b);
610 }
611 
612 template <std::size_t Bits, class Tag>
613 inline bool
615 {
616  return !(a == b);
617 }
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 template <std::size_t Bits, class Tag>
635 inline const base_uint<Bits, Tag>
637 {
638  return base_uint<Bits, Tag>(a) |= b;
639 }
640 
641 template <std::size_t Bits, class Tag>
642 inline const base_uint<Bits, Tag>
644 {
645  return base_uint<Bits, Tag>(a) += b;
646 }
647 
648 //------------------------------------------------------------------------------
649 template <std::size_t Bits, class Tag>
650 inline std::string
652 {
653  return strHex(a.cbegin(), a.cend());
654 }
655 
656 template <std::size_t Bits, class Tag>
657 inline std::ostream&
659 {
660  return out << to_string(u);
661 }
662 
663 #ifndef __INTELLISENSE__
664 static_assert(sizeof(uint128) == 128 / 8, "There should be no padding bytes");
665 static_assert(sizeof(uint160) == 160 / 8, "There should be no padding bytes");
666 static_assert(sizeof(uint256) == 256 / 8, "There should be no padding bytes");
667 #endif
668 
669 } // namespace ripple
670 
671 namespace beast {
672 
673 template <std::size_t Bits, class Tag>
674 struct is_uniquely_represented<ripple::base_uint<Bits, Tag>>
675  : public std::true_type
676 {
677  explicit is_uniquely_represented() = default;
678 };
679 
680 } // namespace beast
681 
682 #endif
ripple::operator>
bool operator>(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:578
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:636
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:474
ripple::uint160
base_uint< 160 > uint160
Definition: base_uint.h:542
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:530
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:585
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::next
base_uint next() const
Definition: base_uint.h:441
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:161
std::array::fill
T fill(T... args)
ripple::base_uint::size
constexpr static std::size_t size()
Definition: base_uint.h:512
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::base_uint::operator~
constexpr base_uint operator~() const
Definition: base_uint.h:336
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:543
beast::is_uniquely_represented
Definition: hash_append.h:95
ripple::base_uint::parseHex
bool parseHex(std::string const &str)
Definition: base_uint.h:506
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:571
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:643
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:525
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:547
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:171
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:622
ripple::uint128
base_uint< 128 > uint128
Definition: base_uint.h:541
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< 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:500
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:517
ripple::base_uint::zero
void zero()
Definition: base_uint.h:535
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:41
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:455
ripple::base_uint::prev
base_uint prev() const
Definition: base_uint.h:448
ripple::base_uint::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:489
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:671