From 4ec3561eb3473638230ef780b41343bc6284b460 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 25 Nov 2015 13:19:48 +0100 Subject: Replace scriptnum_test's normative ScriptNum implementation Compare against the scriptnum from Bitcoin Core 0.10 instead of OpenSSL. Closes #7086. --- src/test/scriptnum10.h | 183 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 src/test/scriptnum10.h (limited to 'src/test/scriptnum10.h') diff --git a/src/test/scriptnum10.h b/src/test/scriptnum10.h new file mode 100644 index 000000000..00419746b --- /dev/null +++ b/src/test/scriptnum10.h @@ -0,0 +1,183 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2013 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_TEST_SCRIPTNUM10_H +#define BITCOIN_TEST_SCRIPTNUM10_H + +#include +#include +#include +#include +#include +#include +#include "assert.h" + +class scriptnum10_error : public std::runtime_error +{ +public: + explicit scriptnum10_error(const std::string& str) : std::runtime_error(str) {} +}; + +class CScriptNum10 +{ +/** + * The ScriptNum implementation from Bitcoin Core 0.10.0, for cross-comparison. + */ +public: + + explicit CScriptNum10(const int64_t& n) + { + m_value = n; + } + + static const size_t nDefaultMaxNumSize = 4; + + explicit CScriptNum10(const std::vector& vch, bool fRequireMinimal, + const size_t nMaxNumSize = nDefaultMaxNumSize) + { + if (vch.size() > nMaxNumSize) { + throw scriptnum10_error("script number overflow"); + } + if (fRequireMinimal && vch.size() > 0) { + // Check that the number is encoded with the minimum possible + // number of bytes. + // + // If the most-significant-byte - excluding the sign bit - is zero + // then we're not minimal. Note how this test also rejects the + // negative-zero encoding, 0x80. + if ((vch.back() & 0x7f) == 0) { + // One exception: if there's more than one byte and the most + // significant bit of the second-most-significant-byte is set + // it would conflict with the sign bit. An example of this case + // is +-255, which encode to 0xff00 and 0xff80 respectively. + // (big-endian). + if (vch.size() <= 1 || (vch[vch.size() - 2] & 0x80) == 0) { + throw scriptnum10_error("non-minimally encoded script number"); + } + } + } + m_value = set_vch(vch); + } + + inline bool operator==(const int64_t& rhs) const { return m_value == rhs; } + inline bool operator!=(const int64_t& rhs) const { return m_value != rhs; } + inline bool operator<=(const int64_t& rhs) const { return m_value <= rhs; } + inline bool operator< (const int64_t& rhs) const { return m_value < rhs; } + inline bool operator>=(const int64_t& rhs) const { return m_value >= rhs; } + inline bool operator> (const int64_t& rhs) const { return m_value > rhs; } + + inline bool operator==(const CScriptNum10& rhs) const { return operator==(rhs.m_value); } + inline bool operator!=(const CScriptNum10& rhs) const { return operator!=(rhs.m_value); } + inline bool operator<=(const CScriptNum10& rhs) const { return operator<=(rhs.m_value); } + inline bool operator< (const CScriptNum10& rhs) const { return operator< (rhs.m_value); } + inline bool operator>=(const CScriptNum10& rhs) const { return operator>=(rhs.m_value); } + inline bool operator> (const CScriptNum10& rhs) const { return operator> (rhs.m_value); } + + inline CScriptNum10 operator+( const int64_t& rhs) const { return CScriptNum10(m_value + rhs);} + inline CScriptNum10 operator-( const int64_t& rhs) const { return CScriptNum10(m_value - rhs);} + inline CScriptNum10 operator+( const CScriptNum10& rhs) const { return operator+(rhs.m_value); } + inline CScriptNum10 operator-( const CScriptNum10& rhs) const { return operator-(rhs.m_value); } + + inline CScriptNum10& operator+=( const CScriptNum10& rhs) { return operator+=(rhs.m_value); } + inline CScriptNum10& operator-=( const CScriptNum10& rhs) { return operator-=(rhs.m_value); } + + inline CScriptNum10 operator-() const + { + assert(m_value != std::numeric_limits::min()); + return CScriptNum10(-m_value); + } + + inline CScriptNum10& operator=( const int64_t& rhs) + { + m_value = rhs; + return *this; + } + + inline CScriptNum10& operator+=( const int64_t& rhs) + { + assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits::max() - rhs) || + (rhs < 0 && m_value >= std::numeric_limits::min() - rhs)); + m_value += rhs; + return *this; + } + + inline CScriptNum10& operator-=( const int64_t& rhs) + { + assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits::min() + rhs) || + (rhs < 0 && m_value <= std::numeric_limits::max() + rhs)); + m_value -= rhs; + return *this; + } + + int getint() const + { + if (m_value > std::numeric_limits::max()) + return std::numeric_limits::max(); + else if (m_value < std::numeric_limits::min()) + return std::numeric_limits::min(); + return m_value; + } + + std::vector getvch() const + { + return serialize(m_value); + } + + static std::vector serialize(const int64_t& value) + { + if(value == 0) + return std::vector(); + + std::vector result; + const bool neg = value < 0; + uint64_t absvalue = neg ? -value : value; + + while(absvalue) + { + result.push_back(absvalue & 0xff); + absvalue >>= 8; + } + +// - If the most significant byte is >= 0x80 and the value is positive, push a +// new zero-byte to make the significant byte < 0x80 again. + +// - If the most significant byte is >= 0x80 and the value is negative, push a +// new 0x80 byte that will be popped off when converting to an integral. + +// - If the most significant byte is < 0x80 and the value is negative, add +// 0x80 to it, since it will be subtracted and interpreted as a negative when +// converting to an integral. + + if (result.back() & 0x80) + result.push_back(neg ? 0x80 : 0); + else if (neg) + result.back() |= 0x80; + + return result; + } + +private: + static int64_t set_vch(const std::vector& vch) + { + if (vch.empty()) + return 0; + + int64_t result = 0; + for (size_t i = 0; i != vch.size(); ++i) + result |= static_cast(vch[i]) << 8*i; + + // If the input vector's most significant byte is 0x80, remove it from + // the result's msb and return a negative. + if (vch.back() & 0x80) + return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1))))); + + return result; + } + + int64_t m_value; +}; + + +#endif // BITCOIN_TEST_BIGNUM_H -- cgit v1.2.3 From fa24439ff3d8ab5b9efaf66ef4dae6713b88cb35 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 13 Dec 2015 17:58:29 +0100 Subject: Bump copyright headers to 2015 --- src/test/scriptnum10.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/test/scriptnum10.h') diff --git a/src/test/scriptnum10.h b/src/test/scriptnum10.h index 00419746b..94dd58526 100644 --- a/src/test/scriptnum10.h +++ b/src/test/scriptnum10.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin Core developers +// Copyright (c) 2009-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -- cgit v1.2.3