Bitcoin Core  31.0.0
P2P Digital Currency
scriptnum10.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-present The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #ifndef BITCOIN_TEST_SCRIPTNUM10_H
7 #define BITCOIN_TEST_SCRIPTNUM10_H
8 
9 #include <cassert>
10 #include <cstdint>
11 #include <limits>
12 #include <stdexcept>
13 #include <string>
14 #include <vector>
15 
16 class scriptnum10_error : public std::runtime_error
17 {
18 public:
19  explicit scriptnum10_error(const std::string& str) : std::runtime_error(str) {}
20 };
21 
23 {
27 public:
28 
29  explicit CScriptNum10(const int64_t& n)
30  {
31  m_value = n;
32  }
33 
34  static const size_t nDefaultMaxNumSize = 4;
35 
36  explicit CScriptNum10(const std::vector<unsigned char>& vch, bool fRequireMinimal,
37  const size_t nMaxNumSize = nDefaultMaxNumSize)
38  {
39  if (vch.size() > nMaxNumSize) {
40  throw scriptnum10_error("script number overflow");
41  }
42  if (fRequireMinimal && vch.size() > 0) {
43  // Check that the number is encoded with the minimum possible
44  // number of bytes.
45  //
46  // If the most-significant-byte - excluding the sign bit - is zero
47  // then we're not minimal. Note how this test also rejects the
48  // negative-zero encoding, 0x80.
49  if ((vch.back() & 0x7f) == 0) {
50  // One exception: if there's more than one byte and the most
51  // significant bit of the second-most-significant-byte is set
52  // it would conflict with the sign bit. An example of this case
53  // is +-255, which encode to 0xff00 and 0xff80 respectively.
54  // (big-endian).
55  if (vch.size() <= 1 || (vch[vch.size() - 2] & 0x80) == 0) {
56  throw scriptnum10_error("non-minimally encoded script number");
57  }
58  }
59  }
60  m_value = set_vch(vch);
61  }
62 
63  inline bool operator==(const int64_t& rhs) const { return m_value == rhs; }
64  inline auto operator<=>(const int64_t& rhs) const { return m_value <=> rhs; }
65 
66  inline bool operator==(const CScriptNum10& rhs) const { return operator==(rhs.m_value); }
67  inline auto operator<=>(const CScriptNum10& rhs) const { return operator<=>(rhs.m_value); }
68 
69  inline CScriptNum10 operator+( const int64_t& rhs) const { return CScriptNum10(m_value + rhs);}
70  inline CScriptNum10 operator-( const int64_t& rhs) const { return CScriptNum10(m_value - rhs);}
71  inline CScriptNum10 operator+( const CScriptNum10& rhs) const { return operator+(rhs.m_value); }
72  inline CScriptNum10 operator-( const CScriptNum10& rhs) const { return operator-(rhs.m_value); }
73 
74  inline CScriptNum10& operator+=( const CScriptNum10& rhs) { return operator+=(rhs.m_value); }
75  inline CScriptNum10& operator-=( const CScriptNum10& rhs) { return operator-=(rhs.m_value); }
76 
77  inline CScriptNum10 operator-() const
78  {
79  assert(m_value != std::numeric_limits<int64_t>::min());
80  return CScriptNum10(-m_value);
81  }
82 
83  inline CScriptNum10& operator=( const int64_t& rhs)
84  {
85  m_value = rhs;
86  return *this;
87  }
88 
89  inline CScriptNum10& operator+=( const int64_t& rhs)
90  {
91  assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) ||
92  (rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs));
93  m_value += rhs;
94  return *this;
95  }
96 
97  inline CScriptNum10& operator-=( const int64_t& rhs)
98  {
99  assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) ||
100  (rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs));
101  m_value -= rhs;
102  return *this;
103  }
104 
105  int getint() const
106  {
107  if (m_value > std::numeric_limits<int>::max())
108  return std::numeric_limits<int>::max();
109  else if (m_value < std::numeric_limits<int>::min())
110  return std::numeric_limits<int>::min();
111  return m_value;
112  }
113 
114  std::vector<unsigned char> getvch() const
115  {
116  return serialize(m_value);
117  }
118 
119  static std::vector<unsigned char> serialize(const int64_t& value)
120  {
121  if(value == 0)
122  return std::vector<unsigned char>();
123 
124  std::vector<unsigned char> result;
125  const bool neg = value < 0;
126  uint64_t absvalue = neg ? -value : value;
127 
128  while(absvalue)
129  {
130  result.push_back(absvalue & 0xff);
131  absvalue >>= 8;
132  }
133 
134 // - If the most significant byte is >= 0x80 and the value is positive, push a
135 // new zero-byte to make the significant byte < 0x80 again.
136 
137 // - If the most significant byte is >= 0x80 and the value is negative, push a
138 // new 0x80 byte that will be popped off when converting to an integral.
139 
140 // - If the most significant byte is < 0x80 and the value is negative, add
141 // 0x80 to it, since it will be subtracted and interpreted as a negative when
142 // converting to an integral.
143 
144  if (result.back() & 0x80)
145  result.push_back(neg ? 0x80 : 0);
146  else if (neg)
147  result.back() |= 0x80;
148 
149  return result;
150  }
151 
152 private:
153  static int64_t set_vch(const std::vector<unsigned char>& vch)
154  {
155  if (vch.empty())
156  return 0;
157 
158  int64_t result = 0;
159  for (size_t i = 0; i != vch.size(); ++i)
160  result |= static_cast<int64_t>(vch[i]) << 8*i;
161 
162  // If the input vector's most significant byte is 0x80, remove it from
163  // the result's msb and return a negative.
164  if (vch.back() & 0x80)
165  return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1)))));
166 
167  return result;
168  }
169 
170  int64_t m_value;
171 };
172 
173 
174 #endif // BITCOIN_TEST_SCRIPTNUM10_H
CScriptNum10(const std::vector< unsigned char > &vch, bool fRequireMinimal, const size_t nMaxNumSize=nDefaultMaxNumSize)
Definition: scriptnum10.h:36
CScriptNum10 & operator-=(const CScriptNum10 &rhs)
Definition: scriptnum10.h:75
assert(!tx.IsCoinBase())
CScriptNum10 operator-(const int64_t &rhs) const
Definition: scriptnum10.h:70
int getint() const
Definition: scriptnum10.h:105
scriptnum10_error(const std::string &str)
Definition: scriptnum10.h:19
Definition: common.h:29
CScriptNum10 operator-(const CScriptNum10 &rhs) const
Definition: scriptnum10.h:72
bool operator==(const CScriptNum10 &rhs) const
Definition: scriptnum10.h:66
static const size_t nDefaultMaxNumSize
Definition: scriptnum10.h:34
static int64_t set_vch(const std::vector< unsigned char > &vch)
Definition: scriptnum10.h:153
std::vector< unsigned char > getvch() const
Definition: scriptnum10.h:114
CScriptNum10 operator-() const
Definition: scriptnum10.h:77
CScriptNum10 operator+(const CScriptNum10 &rhs) const
Definition: scriptnum10.h:71
CScriptNum10 & operator-=(const int64_t &rhs)
Definition: scriptnum10.h:97
int64_t m_value
Definition: scriptnum10.h:170
static std::vector< unsigned char > serialize(const int64_t &value)
Definition: scriptnum10.h:119
CScriptNum10 operator+(const int64_t &rhs) const
Definition: scriptnum10.h:69
auto result
Definition: common-types.h:74
CScriptNum10 & operator=(const int64_t &rhs)
Definition: scriptnum10.h:83
CScriptNum10 & operator+=(const CScriptNum10 &rhs)
Definition: scriptnum10.h:74
CScriptNum10(const int64_t &n)
The ScriptNum implementation from Bitcoin Core 0.10.0, for cross-comparison.
Definition: scriptnum10.h:29
bool operator==(const int64_t &rhs) const
Definition: scriptnum10.h:63
CScriptNum10 & operator+=(const int64_t &rhs)
Definition: scriptnum10.h:89