| 279 | }; |
| 280 | |
| 281 | class CScriptNum |
| 282 | { |
| 283 | /** |
| 284 | * Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte integers. |
| 285 | * The semantics are subtle, though: operands must be in the range [-2^31 +1...2^31 -1], |
| 286 | * but results may overflow (and are valid as long as they are not used in a subsequent |
| 287 | * numeric operation). CScriptNum enforces those semantics by storing results as |
| 288 | * an int64 and allowing out-of-range values to be returned as a vector of bytes but |
| 289 | * throwing an exception if arithmetic is done or the result is interpreted as an integer. |
| 290 | */ |
| 291 | public: |
| 292 | |
| 293 | explicit CScriptNum(const int64_t& n) |
| 294 | { |
| 295 | m_value = n; |
| 296 | } |
| 297 | |
| 298 | static const size_t nDefaultMaxNumSize = 4; |
| 299 | |
| 300 | explicit CScriptNum(const std::vector<unsigned char>& vch, bool fRequireMinimal, |
| 301 | const size_t nMaxNumSize = nDefaultMaxNumSize) |
| 302 | { |
| 303 | if (vch.size() > nMaxNumSize) { |
| 304 | throw scriptnum_error("script number overflow"); |
| 305 | } |
| 306 | if (fRequireMinimal && vch.size() > 0) { |
| 307 | // Check that the number is encoded with the minimum possible |
| 308 | // number of bytes. |
| 309 | // |
| 310 | // If the most-significant-byte - excluding the sign bit - is zero |
| 311 | // then we're not minimal. Note how this test also rejects the |
| 312 | // negative-zero encoding, 0x80. |
| 313 | if ((vch.back() & 0x7f) == 0) { |
| 314 | // One exception: if there's more than one byte and the most |
| 315 | // significant bit of the second-most-significant-byte is set |
| 316 | // it would conflict with the sign bit. An example of this case |
| 317 | // is +-255, which encode to 0xff00 and 0xff80 respectively. |
| 318 | // (big-endian). |
| 319 | if (vch.size() <= 1 || (vch[vch.size() - 2] & 0x80) == 0) { |
| 320 | throw scriptnum_error("non-minimally encoded script number"); |
| 321 | } |
| 322 | } |
| 323 | } |
| 324 | m_value = set_vch(vch); |
| 325 | } |
| 326 | |
| 327 | inline bool operator==(const int64_t& rhs) const { return m_value == rhs; } |
| 328 | inline bool operator!=(const int64_t& rhs) const { return m_value != rhs; } |
| 329 | inline bool operator<=(const int64_t& rhs) const { return m_value <= rhs; } |
| 330 | inline bool operator< (const int64_t& rhs) const { return m_value < rhs; } |
| 331 | inline bool operator>=(const int64_t& rhs) const { return m_value >= rhs; } |
| 332 | inline bool operator> (const int64_t& rhs) const { return m_value > rhs; } |
| 333 | |
| 334 | inline bool operator==(const CScriptNum& rhs) const { return operator==(rhs.m_value); } |
| 335 | inline bool operator!=(const CScriptNum& rhs) const { return operator!=(rhs.m_value); } |
| 336 | inline bool operator<=(const CScriptNum& rhs) const { return operator<=(rhs.m_value); } |
| 337 | inline bool operator< (const CScriptNum& rhs) const { return operator< (rhs.m_value); } |
| 338 | inline bool operator>=(const CScriptNum& rhs) const { return operator>=(rhs.m_value); } |
no outgoing calls