Skip to content

Commit d8368a0

Browse files
committed
Merge pull request #7095
4ec3561 Replace scriptnum_test's normative ScriptNum implementation (Wladimir J. van der Laan)
2 parents 9502b7f + 4ec3561 commit d8368a0

File tree

4 files changed

+206
-200
lines changed

4 files changed

+206
-200
lines changed

src/Makefile.test.include

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.r
3535

3636
BITCOIN_TESTS =\
3737
test/arith_uint256_tests.cpp \
38-
test/bignum.h \
38+
test/scriptnum10.h \
3939
test/addrman_tests.cpp \
4040
test/alert_tests.cpp \
4141
test/allocator_tests.cpp \

src/test/bignum.h

Lines changed: 0 additions & 180 deletions
This file was deleted.

src/test/scriptnum10.h

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

0 commit comments

Comments
 (0)