mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-02-11 06:34:31 +00:00
Remove bignum dependency for scripts
Rebased-From: 48d8eb1 27bff74 4f497cd 05e3ecf 90320d6 b1fdd54
This commit is contained in:
parent
5baa4a90e3
commit
84efe0ec22
@ -125,7 +125,7 @@ public:
|
||||
CTransaction txNew;
|
||||
txNew.vin.resize(1);
|
||||
txNew.vout.resize(1);
|
||||
txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
|
||||
txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
|
||||
txNew.vout[0].nValue = 50 * COIN;
|
||||
txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
|
||||
genesis.vtx.push_back(txNew);
|
||||
|
@ -355,7 +355,7 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
|
||||
}
|
||||
++nExtraNonce;
|
||||
unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
|
||||
pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CBigNum(nExtraNonce)) + COINBASE_FLAGS;
|
||||
pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
|
||||
assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100);
|
||||
|
||||
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
#include "script.h"
|
||||
|
||||
#include "bignum.h"
|
||||
#include "core.h"
|
||||
#include "hash.h"
|
||||
#include "key.h"
|
||||
@ -25,22 +24,13 @@ typedef vector<unsigned char> valtype;
|
||||
static const valtype vchFalse(0);
|
||||
static const valtype vchZero(0);
|
||||
static const valtype vchTrue(1, 1);
|
||||
static const CBigNum bnZero(0);
|
||||
static const CBigNum bnOne(1);
|
||||
static const CBigNum bnFalse(0);
|
||||
static const CBigNum bnTrue(1);
|
||||
static const size_t nMaxNumSize = 4;
|
||||
static const CScriptNum bnZero(0);
|
||||
static const CScriptNum bnOne(1);
|
||||
static const CScriptNum bnFalse(0);
|
||||
static const CScriptNum bnTrue(1);
|
||||
|
||||
bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char> &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags);
|
||||
|
||||
CBigNum CastToBigNum(const valtype& vch)
|
||||
{
|
||||
if (vch.size() > nMaxNumSize)
|
||||
throw runtime_error("CastToBigNum() : overflow");
|
||||
// Get rid of extra leading zeros
|
||||
return CBigNum(CBigNum(vch).getvch());
|
||||
}
|
||||
|
||||
bool CastToBool(const valtype& vch)
|
||||
{
|
||||
for (unsigned int i = 0; i < vch.size(); i++)
|
||||
@ -306,7 +296,6 @@ bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) {
|
||||
|
||||
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CScript::const_iterator pc = script.begin();
|
||||
CScript::const_iterator pend = script.end();
|
||||
CScript::const_iterator pbegincodehash = script.begin();
|
||||
@ -380,7 +369,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||
case OP_16:
|
||||
{
|
||||
// ( -- value)
|
||||
CBigNum bn((int)opcode - (int)(OP_1 - 1));
|
||||
CScriptNum bn((int)opcode - (int)(OP_1 - 1));
|
||||
stack.push_back(bn.getvch());
|
||||
}
|
||||
break;
|
||||
@ -556,7 +545,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||
case OP_DEPTH:
|
||||
{
|
||||
// -- stacksize
|
||||
CBigNum bn(stack.size());
|
||||
CScriptNum bn(stack.size());
|
||||
stack.push_back(bn.getvch());
|
||||
}
|
||||
break;
|
||||
@ -606,7 +595,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||
// (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
|
||||
if (stack.size() < 2)
|
||||
return false;
|
||||
int n = CastToBigNum(stacktop(-1)).getint();
|
||||
int n = CScriptNum(stacktop(-1)).getint();
|
||||
popstack(stack);
|
||||
if (n < 0 || n >= (int)stack.size())
|
||||
return false;
|
||||
@ -654,7 +643,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||
// (in -- in size)
|
||||
if (stack.size() < 1)
|
||||
return false;
|
||||
CBigNum bn(stacktop(-1).size());
|
||||
CScriptNum bn(stacktop(-1).size());
|
||||
stack.push_back(bn.getvch());
|
||||
}
|
||||
break;
|
||||
@ -705,7 +694,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||
// (in -- out)
|
||||
if (stack.size() < 1)
|
||||
return false;
|
||||
CBigNum bn = CastToBigNum(stacktop(-1));
|
||||
CScriptNum bn(stacktop(-1));
|
||||
switch (opcode)
|
||||
{
|
||||
case OP_1ADD: bn += bnOne; break;
|
||||
@ -738,9 +727,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||
// (x1 x2 -- out)
|
||||
if (stack.size() < 2)
|
||||
return false;
|
||||
CBigNum bn1 = CastToBigNum(stacktop(-2));
|
||||
CBigNum bn2 = CastToBigNum(stacktop(-1));
|
||||
CBigNum bn;
|
||||
CScriptNum bn1(stacktop(-2));
|
||||
CScriptNum bn2(stacktop(-1));
|
||||
CScriptNum bn(0);
|
||||
switch (opcode)
|
||||
{
|
||||
case OP_ADD:
|
||||
@ -783,9 +772,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||
// (x min max -- out)
|
||||
if (stack.size() < 3)
|
||||
return false;
|
||||
CBigNum bn1 = CastToBigNum(stacktop(-3));
|
||||
CBigNum bn2 = CastToBigNum(stacktop(-2));
|
||||
CBigNum bn3 = CastToBigNum(stacktop(-1));
|
||||
CScriptNum bn1(stacktop(-3));
|
||||
CScriptNum bn2(stacktop(-2));
|
||||
CScriptNum bn3(stacktop(-1));
|
||||
bool fValue = (bn2 <= bn1 && bn1 < bn3);
|
||||
popstack(stack);
|
||||
popstack(stack);
|
||||
@ -882,7 +871,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||
if ((int)stack.size() < i)
|
||||
return false;
|
||||
|
||||
int nKeysCount = CastToBigNum(stacktop(-i)).getint();
|
||||
int nKeysCount = CScriptNum(stacktop(-i)).getint();
|
||||
if (nKeysCount < 0 || nKeysCount > 20)
|
||||
return false;
|
||||
nOpCount += nKeysCount;
|
||||
@ -893,7 +882,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||
if ((int)stack.size() < i)
|
||||
return false;
|
||||
|
||||
int nSigsCount = CastToBigNum(stacktop(-i)).getint();
|
||||
int nSigsCount = CScriptNum(stacktop(-i)).getint();
|
||||
if (nSigsCount < 0 || nSigsCount > nKeysCount)
|
||||
return false;
|
||||
int isig = ++i;
|
||||
|
198
src/script.h
198
src/script.h
@ -6,7 +6,6 @@
|
||||
#ifndef H_BITCOIN_SCRIPT
|
||||
#define H_BITCOIN_SCRIPT
|
||||
|
||||
#include "bignum.h"
|
||||
#include "key.h"
|
||||
#include "util.h"
|
||||
|
||||
@ -25,6 +24,155 @@ class CTransaction;
|
||||
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
|
||||
static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes
|
||||
|
||||
class scriptnum_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit scriptnum_error(const std::string& str) : std::runtime_error(str) {}
|
||||
};
|
||||
|
||||
class CScriptNum
|
||||
{
|
||||
// Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte integers.
|
||||
// The semantics are subtle, though: operands must be in the range [-2^31 +1...2^31 -1],
|
||||
// but results may overflow (and are valid as long as they are not used in a subsequent
|
||||
// numeric operation). CScriptNum enforces those semantics by storing results as
|
||||
// an int64 and allowing out-of-range values to be returned as a vector of bytes but
|
||||
// throwing an exception if arithmetic is done or the result is interpreted as an integer.
|
||||
public:
|
||||
|
||||
explicit CScriptNum(const int64_t& n)
|
||||
{
|
||||
m_value = n;
|
||||
}
|
||||
|
||||
explicit CScriptNum(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
if (vch.size() > nMaxNumSize)
|
||||
throw scriptnum_error("CScriptNum(const std::vector<unsigned char>&) : overflow");
|
||||
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 CScriptNum& rhs) const { return operator==(rhs.m_value); }
|
||||
inline bool operator!=(const CScriptNum& rhs) const { return operator!=(rhs.m_value); }
|
||||
inline bool operator<=(const CScriptNum& rhs) const { return operator<=(rhs.m_value); }
|
||||
inline bool operator< (const CScriptNum& rhs) const { return operator< (rhs.m_value); }
|
||||
inline bool operator>=(const CScriptNum& rhs) const { return operator>=(rhs.m_value); }
|
||||
inline bool operator> (const CScriptNum& rhs) const { return operator> (rhs.m_value); }
|
||||
|
||||
inline CScriptNum operator+( const int64_t& rhs) const { return CScriptNum(m_value + rhs);}
|
||||
inline CScriptNum operator-( const int64_t& rhs) const { return CScriptNum(m_value - rhs);}
|
||||
inline CScriptNum operator+( const CScriptNum& rhs) const { return operator+(rhs.m_value); }
|
||||
inline CScriptNum operator-( const CScriptNum& rhs) const { return operator-(rhs.m_value); }
|
||||
|
||||
inline CScriptNum& operator+=( const CScriptNum& rhs) { return operator+=(rhs.m_value); }
|
||||
inline CScriptNum& operator-=( const CScriptNum& rhs) { return operator-=(rhs.m_value); }
|
||||
|
||||
inline CScriptNum operator-() const
|
||||
{
|
||||
assert(m_value != std::numeric_limits<int64_t>::min());
|
||||
return CScriptNum(-m_value);
|
||||
}
|
||||
|
||||
inline CScriptNum& operator=( const int64_t& rhs)
|
||||
{
|
||||
m_value = rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline CScriptNum& operator+=( const int64_t& rhs)
|
||||
{
|
||||
assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) ||
|
||||
(rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs));
|
||||
m_value += rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline CScriptNum& operator-=( const int64_t& rhs)
|
||||
{
|
||||
assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) ||
|
||||
(rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs));
|
||||
m_value -= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int getint() const
|
||||
{
|
||||
if (m_value > std::numeric_limits<int>::max())
|
||||
return std::numeric_limits<int>::max();
|
||||
else if (m_value < std::numeric_limits<int>::min())
|
||||
return std::numeric_limits<int>::min();
|
||||
return m_value;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> getvch() const
|
||||
{
|
||||
return serialize(m_value);
|
||||
}
|
||||
|
||||
static std::vector<unsigned char> serialize(const int64_t& value)
|
||||
{
|
||||
if(value == 0)
|
||||
return std::vector<unsigned char>();
|
||||
|
||||
std::vector<unsigned char> 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;
|
||||
}
|
||||
|
||||
static const size_t nMaxNumSize = 4;
|
||||
|
||||
private:
|
||||
static int64_t set_vch(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
if (vch.empty())
|
||||
return 0;
|
||||
|
||||
int64_t result = 0;
|
||||
for (size_t i = 0; i != vch.size(); ++i)
|
||||
result |= static_cast<int64_t>(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 -(result & ~(0x80 << (8 * (vch.size() - 1))));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t m_value;
|
||||
};
|
||||
|
||||
/** Signature hash types/flags */
|
||||
enum
|
||||
{
|
||||
@ -225,7 +373,7 @@ const char* GetOpName(opcodetype opcode);
|
||||
inline std::string ValueString(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
if (vch.size() <= 4)
|
||||
return strprintf("%d", CBigNum(vch).getint());
|
||||
return strprintf("%d", CScriptNum(vch).getint());
|
||||
else
|
||||
return HexStr(vch);
|
||||
}
|
||||
@ -261,26 +409,10 @@ protected:
|
||||
}
|
||||
else
|
||||
{
|
||||
CBigNum bn(n);
|
||||
*this << bn.getvch();
|
||||
*this << CScriptNum::serialize(n);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CScript& push_uint64(uint64_t n)
|
||||
{
|
||||
if (n >= 1 && n <= 16)
|
||||
{
|
||||
push_back(n + (OP_1 - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
CBigNum bn(n);
|
||||
*this << bn.getvch();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
CScript() { }
|
||||
CScript(const CScript& b) : std::vector<unsigned char>(b.begin(), b.end()) { }
|
||||
@ -303,35 +435,15 @@ public:
|
||||
}
|
||||
|
||||
|
||||
//explicit CScript(char b) is not portable. Use 'signed char' or 'unsigned char'.
|
||||
explicit CScript(signed char b) { operator<<(b); }
|
||||
explicit CScript(short b) { operator<<(b); }
|
||||
explicit CScript(int b) { operator<<(b); }
|
||||
explicit CScript(long b) { operator<<(b); }
|
||||
explicit CScript(long long b) { operator<<(b); }
|
||||
explicit CScript(unsigned char b) { operator<<(b); }
|
||||
explicit CScript(unsigned int b) { operator<<(b); }
|
||||
explicit CScript(unsigned short b) { operator<<(b); }
|
||||
explicit CScript(unsigned long b) { operator<<(b); }
|
||||
explicit CScript(unsigned long long b) { operator<<(b); }
|
||||
CScript(int64_t b) { operator<<(b); }
|
||||
|
||||
explicit CScript(opcodetype b) { operator<<(b); }
|
||||
explicit CScript(const uint256& b) { operator<<(b); }
|
||||
explicit CScript(const CBigNum& b) { operator<<(b); }
|
||||
explicit CScript(const CScriptNum& b) { operator<<(b); }
|
||||
explicit CScript(const std::vector<unsigned char>& b) { operator<<(b); }
|
||||
|
||||
|
||||
//CScript& operator<<(char b) is not portable. Use 'signed char' or 'unsigned char'.
|
||||
CScript& operator<<(signed char b) { return push_int64(b); }
|
||||
CScript& operator<<(short b) { return push_int64(b); }
|
||||
CScript& operator<<(int b) { return push_int64(b); }
|
||||
CScript& operator<<(long b) { return push_int64(b); }
|
||||
CScript& operator<<(long long b) { return push_int64(b); }
|
||||
CScript& operator<<(unsigned char b) { return push_uint64(b); }
|
||||
CScript& operator<<(unsigned int b) { return push_uint64(b); }
|
||||
CScript& operator<<(unsigned short b) { return push_uint64(b); }
|
||||
CScript& operator<<(unsigned long b) { return push_uint64(b); }
|
||||
CScript& operator<<(unsigned long long b) { return push_uint64(b); }
|
||||
CScript& operator<<(int64_t b) { return push_int64(b); }
|
||||
|
||||
CScript& operator<<(opcodetype opcode)
|
||||
{
|
||||
@ -363,7 +475,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
CScript& operator<<(const CBigNum& b)
|
||||
CScript& operator<<(const CScriptNum& b)
|
||||
{
|
||||
*this << b.getvch();
|
||||
return *this;
|
||||
|
@ -61,6 +61,7 @@ test_bitcoin_SOURCES = \
|
||||
transaction_tests.cpp \
|
||||
uint256_tests.cpp \
|
||||
util_tests.cpp \
|
||||
scriptnum_tests.cpp \
|
||||
sighash_tests.cpp \
|
||||
$(JSON_TEST_FILES) $(RAW_TEST_FILES)
|
||||
|
||||
|
@ -257,7 +257,10 @@
|
||||
["1","0xba", "0xba == OP_NOP10 + 1"],
|
||||
|
||||
["2147483648", "1ADD 1", "We cannot do math on 5-byte integers"],
|
||||
["2147483648", "NEGATE 1", "We cannot do math on 5-byte integers"],
|
||||
["-2147483648", "1ADD 1", "Because we use a sign bit, -2147483648 is also 5 bytes"],
|
||||
["2147483647", "1ADD 1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
|
||||
["2147483648", "1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
|
||||
|
||||
["1", "1 ENDIF", "ENDIF without IF"],
|
||||
["1", "IF 1", "IF without ENDIF"],
|
||||
|
@ -97,6 +97,9 @@
|
||||
["8388608", "SIZE 4 EQUAL"],
|
||||
["2147483647", "SIZE 4 EQUAL"],
|
||||
["2147483648", "SIZE 5 EQUAL"],
|
||||
["549755813887", "SIZE 5 EQUAL"],
|
||||
["549755813888", "SIZE 6 EQUAL"],
|
||||
["9223372036854775807", "SIZE 8 EQUAL"],
|
||||
["-1", "SIZE 1 EQUAL"],
|
||||
["-127", "SIZE 1 EQUAL"],
|
||||
["-128", "SIZE 2 EQUAL"],
|
||||
@ -106,6 +109,9 @@
|
||||
["-8388608", "SIZE 4 EQUAL"],
|
||||
["-2147483647", "SIZE 4 EQUAL"],
|
||||
["-2147483648", "SIZE 5 EQUAL"],
|
||||
["-549755813887", "SIZE 5 EQUAL"],
|
||||
["-549755813888", "SIZE 6 EQUAL"],
|
||||
["-9223372036854775807", "SIZE 8 EQUAL"],
|
||||
["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL"],
|
||||
|
||||
|
||||
@ -306,6 +312,9 @@
|
||||
["8388608", "0x04 0x00008000 EQUAL"],
|
||||
["2147483647", "0x04 0xFFFFFF7F EQUAL"],
|
||||
["2147483648", "0x05 0x0000008000 EQUAL"],
|
||||
["549755813887", "0x05 0xFFFFFFFF7F EQUAL"],
|
||||
["549755813888", "0x06 0xFFFFFFFF7F EQUAL"],
|
||||
["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL"],
|
||||
["-1", "0x01 0x81 EQUAL", "Numbers are little-endian with the MSB being a sign bit"],
|
||||
["-127", "0x01 0xFF EQUAL"],
|
||||
["-128", "0x02 0x8080 EQUAL"],
|
||||
@ -315,6 +324,10 @@
|
||||
["-8388608", "0x04 0x00008080 EQUAL"],
|
||||
["-2147483647", "0x04 0xFFFFFFFF EQUAL"],
|
||||
["-2147483648", "0x05 0x0000008080 EQUAL"],
|
||||
["-4294967295", "0x05 0xFFFFFFFF80 EQUAL"],
|
||||
["-549755813887", "0x05 0xFFFFFFFFFF EQUAL"],
|
||||
["-549755813888", "0x06 0x000000008080 EQUAL"],
|
||||
["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL"],
|
||||
|
||||
["2147483647", "1ADD 2147483648 EQUAL", "We can do math on 4-byte integers, and compare 5-byte ones"],
|
||||
["2147483647", "1ADD 1"],
|
||||
|
196
src/test/scriptnum_tests.cpp
Normal file
196
src/test/scriptnum_tests.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
// Copyright (c) 2012-2014 The Bitcoin Core developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "bignum.h"
|
||||
#include "script.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
BOOST_AUTO_TEST_SUITE(scriptnum_tests)
|
||||
|
||||
static const int64_t values[] = \
|
||||
{ 0, 1, CHAR_MIN, CHAR_MAX, UCHAR_MAX, SHRT_MIN, USHRT_MAX, INT_MIN, INT_MAX, UINT_MAX, LONG_MIN, LONG_MAX };
|
||||
static const int64_t offsets[] = { 1, 0x79, 0x80, 0x81, 0xFF, 0x7FFF, 0x8000, 0xFFFF, 0x10000};
|
||||
|
||||
static bool verify(const CBigNum& bignum, const CScriptNum& scriptnum)
|
||||
{
|
||||
return bignum.getvch() == scriptnum.getvch() && bignum.getint() == scriptnum.getint();
|
||||
}
|
||||
|
||||
static void CheckCreateVch(const int64_t& num)
|
||||
{
|
||||
CBigNum bignum(num);
|
||||
CScriptNum scriptnum(num);
|
||||
BOOST_CHECK(verify(bignum, scriptnum));
|
||||
|
||||
CBigNum bignum2(bignum.getvch());
|
||||
CScriptNum scriptnum2(scriptnum.getvch());
|
||||
BOOST_CHECK(verify(bignum2, scriptnum2));
|
||||
|
||||
CBigNum bignum3(scriptnum2.getvch());
|
||||
CScriptNum scriptnum3(bignum2.getvch());
|
||||
BOOST_CHECK(verify(bignum3, scriptnum3));
|
||||
}
|
||||
|
||||
static void CheckCreateInt(const int64_t& num)
|
||||
{
|
||||
CBigNum bignum(num);
|
||||
CScriptNum scriptnum(num);
|
||||
BOOST_CHECK(verify(bignum, scriptnum));
|
||||
BOOST_CHECK(verify(bignum.getint(), CScriptNum(scriptnum.getint())));
|
||||
BOOST_CHECK(verify(scriptnum.getint(), CScriptNum(bignum.getint())));
|
||||
BOOST_CHECK(verify(CBigNum(scriptnum.getint()).getint(), CScriptNum(CScriptNum(bignum.getint()).getint())));
|
||||
}
|
||||
|
||||
|
||||
static void CheckAdd(const int64_t& num1, const int64_t& num2)
|
||||
{
|
||||
const CBigNum bignum1(num1);
|
||||
const CBigNum bignum2(num2);
|
||||
const CScriptNum scriptnum1(num1);
|
||||
const CScriptNum scriptnum2(num2);
|
||||
CBigNum bignum3(num1);
|
||||
CBigNum bignum4(num1);
|
||||
CScriptNum scriptnum3(num1);
|
||||
CScriptNum scriptnum4(num1);
|
||||
|
||||
// int64_t overflow is undefined.
|
||||
bool invalid = (((num2 > 0) && (num1 > (std::numeric_limits<int64_t>::max() - num2))) ||
|
||||
((num2 < 0) && (num1 < (std::numeric_limits<int64_t>::min() - num2))));
|
||||
if (!invalid)
|
||||
{
|
||||
BOOST_CHECK(verify(bignum1 + bignum2, scriptnum1 + scriptnum2));
|
||||
BOOST_CHECK(verify(bignum1 + bignum2, scriptnum1 + num2));
|
||||
BOOST_CHECK(verify(bignum1 + bignum2, scriptnum2 + num1));
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckNegate(const int64_t& num)
|
||||
{
|
||||
const CBigNum bignum(num);
|
||||
const CScriptNum scriptnum(num);
|
||||
|
||||
// -INT64_MIN is undefined
|
||||
if (num != std::numeric_limits<int64_t>::min())
|
||||
BOOST_CHECK(verify(-bignum, -scriptnum));
|
||||
}
|
||||
|
||||
static void CheckSubtract(const int64_t& num1, const int64_t& num2)
|
||||
{
|
||||
const CBigNum bignum1(num1);
|
||||
const CBigNum bignum2(num2);
|
||||
const CScriptNum scriptnum1(num1);
|
||||
const CScriptNum scriptnum2(num2);
|
||||
bool invalid = false;
|
||||
|
||||
// int64_t overflow is undefined.
|
||||
invalid = ((num2 > 0 && num1 < std::numeric_limits<int64_t>::min() + num2) ||
|
||||
(num2 < 0 && num1 > std::numeric_limits<int64_t>::max() + num2));
|
||||
if (!invalid)
|
||||
{
|
||||
BOOST_CHECK(verify(bignum1 - bignum2, scriptnum1 - scriptnum2));
|
||||
BOOST_CHECK(verify(bignum1 - bignum2, scriptnum1 - num2));
|
||||
}
|
||||
|
||||
invalid = ((num1 > 0 && num2 < std::numeric_limits<int64_t>::min() + num1) ||
|
||||
(num1 < 0 && num2 > std::numeric_limits<int64_t>::max() + num1));
|
||||
if (!invalid)
|
||||
{
|
||||
BOOST_CHECK(verify(bignum2 - bignum1, scriptnum2 - scriptnum1));
|
||||
BOOST_CHECK(verify(bignum2 - bignum1, scriptnum2 - num1));
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckCompare(const int64_t& num1, const int64_t& num2)
|
||||
{
|
||||
const CBigNum bignum1(num1);
|
||||
const CBigNum bignum2(num2);
|
||||
const CScriptNum scriptnum1(num1);
|
||||
const CScriptNum scriptnum2(num2);
|
||||
|
||||
BOOST_CHECK((bignum1 == bignum1) == (scriptnum1 == scriptnum1));
|
||||
BOOST_CHECK((bignum1 != bignum1) == (scriptnum1 != scriptnum1));
|
||||
BOOST_CHECK((bignum1 < bignum1) == (scriptnum1 < scriptnum1));
|
||||
BOOST_CHECK((bignum1 > bignum1) == (scriptnum1 > scriptnum1));
|
||||
BOOST_CHECK((bignum1 >= bignum1) == (scriptnum1 >= scriptnum1));
|
||||
BOOST_CHECK((bignum1 <= bignum1) == (scriptnum1 <= scriptnum1));
|
||||
|
||||
BOOST_CHECK((bignum1 == bignum1) == (scriptnum1 == num1));
|
||||
BOOST_CHECK((bignum1 != bignum1) == (scriptnum1 != num1));
|
||||
BOOST_CHECK((bignum1 < bignum1) == (scriptnum1 < num1));
|
||||
BOOST_CHECK((bignum1 > bignum1) == (scriptnum1 > num1));
|
||||
BOOST_CHECK((bignum1 >= bignum1) == (scriptnum1 >= num1));
|
||||
BOOST_CHECK((bignum1 <= bignum1) == (scriptnum1 <= num1));
|
||||
|
||||
BOOST_CHECK((bignum1 == bignum2) == (scriptnum1 == scriptnum2));
|
||||
BOOST_CHECK((bignum1 != bignum2) == (scriptnum1 != scriptnum2));
|
||||
BOOST_CHECK((bignum1 < bignum2) == (scriptnum1 < scriptnum2));
|
||||
BOOST_CHECK((bignum1 > bignum2) == (scriptnum1 > scriptnum2));
|
||||
BOOST_CHECK((bignum1 >= bignum2) == (scriptnum1 >= scriptnum2));
|
||||
BOOST_CHECK((bignum1 <= bignum2) == (scriptnum1 <= scriptnum2));
|
||||
|
||||
BOOST_CHECK((bignum1 == bignum2) == (scriptnum1 == num2));
|
||||
BOOST_CHECK((bignum1 != bignum2) == (scriptnum1 != num2));
|
||||
BOOST_CHECK((bignum1 < bignum2) == (scriptnum1 < num2));
|
||||
BOOST_CHECK((bignum1 > bignum2) == (scriptnum1 > num2));
|
||||
BOOST_CHECK((bignum1 >= bignum2) == (scriptnum1 >= num2));
|
||||
BOOST_CHECK((bignum1 <= bignum2) == (scriptnum1 <= num2));
|
||||
}
|
||||
|
||||
static void RunCreate(const int64_t& num)
|
||||
{
|
||||
CheckCreateInt(num);
|
||||
CScriptNum scriptnum(num);
|
||||
if (scriptnum.getvch().size() <= CScriptNum::nMaxNumSize)
|
||||
CheckCreateVch(num);
|
||||
else
|
||||
{
|
||||
BOOST_CHECK_THROW (CheckCreateVch(num), scriptnum_error);
|
||||
}
|
||||
}
|
||||
|
||||
static void RunOperators(const int64_t& num1, const int64_t& num2)
|
||||
{
|
||||
CheckAdd(num1, num2);
|
||||
CheckSubtract(num1, num2);
|
||||
CheckNegate(num1);
|
||||
CheckCompare(num1, num2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(creation)
|
||||
{
|
||||
for(size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i)
|
||||
{
|
||||
for(size_t j = 0; j < sizeof(offsets) / sizeof(offsets[0]); ++j)
|
||||
{
|
||||
RunCreate(values[i]);
|
||||
RunCreate(values[i] + offsets[j]);
|
||||
RunCreate(values[i] - offsets[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(operators)
|
||||
{
|
||||
for(size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i)
|
||||
{
|
||||
for(size_t j = 0; j < sizeof(offsets) / sizeof(offsets[0]); ++j)
|
||||
{
|
||||
RunOperators(values[i], values[i]);
|
||||
RunOperators(values[i], -values[i]);
|
||||
RunOperators(values[i], values[j]);
|
||||
RunOperators(values[i], -values[j]);
|
||||
RunOperators(values[i] + values[j], values[j]);
|
||||
RunOperators(values[i] + values[j], -values[j]);
|
||||
RunOperators(values[i] - values[j], values[j]);
|
||||
RunOperators(values[i] - values[j], -values[j]);
|
||||
RunOperators(values[i] + values[j], values[i] + values[j]);
|
||||
RunOperators(values[i] + values[j], values[i] - values[j]);
|
||||
RunOperators(values[i] - values[j], values[i] + values[j]);
|
||||
RunOperators(values[i] - values[j], values[i] - values[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
x
Reference in New Issue
Block a user