Changeset View
Changeset View
Standalone View
Standalone View
src/test/op_endian_reverse_tests.cpp
- This file was added.
// Copyright (c) 2020 The Bitcoin developers | |||||
// Distributed under the MIT software license, see the accompanying | |||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | |||||
#include <script/interpreter.h> | |||||
#include <script/script.h> | |||||
#include <test/lcg.h> | |||||
#include <test/test_bitcoin.h> | |||||
#include <boost/test/unit_test.hpp> | |||||
typedef std::vector<uint8_t> valtype; | |||||
typedef std::vector<valtype> stacktype; | |||||
BOOST_FIXTURE_TEST_SUITE(op_endian_reverse_tests, BasicTestingSetup) | |||||
static void CheckErrorWithFlags(const uint32_t flags, | |||||
const stacktype &original_stack, | |||||
const CScript &script, | |||||
const ScriptError expected) { | |||||
BaseSignatureChecker sigchecker; | |||||
ScriptError err = ScriptError::OK; | |||||
stacktype stack{original_stack}; | |||||
bool r = EvalScript(stack, script, flags, sigchecker, &err); | |||||
BOOST_CHECK(!r); | |||||
BOOST_CHECK(err == expected); | |||||
} | |||||
static void CheckPassWithFlags(const uint32_t flags, | |||||
const stacktype &original_stack, | |||||
const CScript &script, | |||||
const stacktype &expected) { | |||||
BaseSignatureChecker sigchecker; | |||||
ScriptError err = ScriptError::OK; | |||||
stacktype stack{original_stack}; | |||||
bool r = EvalScript(stack, script, flags, sigchecker, &err); | |||||
BOOST_CHECK(r); | |||||
BOOST_CHECK(err == ScriptError::OK); | |||||
BOOST_CHECK(stack == expected); | |||||
} | |||||
/** | |||||
* Verifies that the given error occurs with OP_ENDIAN_REVERSE enabled | |||||
* and that BAD_OPCODE occurs if disabled. | |||||
*/ | |||||
static void CheckErrorIfEnabled(const uint32_t flags, | |||||
const stacktype &original_stack, | |||||
const CScript &script, | |||||
const ScriptError expected) { | |||||
CheckErrorWithFlags(flags | SCRIPT_ENABLE_OP_ENDIAN_REVERSE, original_stack, | |||||
script, expected); | |||||
CheckErrorWithFlags(flags & ~SCRIPT_ENABLE_OP_ENDIAN_REVERSE, | |||||
original_stack, script, ScriptError::BAD_OPCODE); | |||||
} | |||||
/** | |||||
* Verifies that the given stack results with OP_ENDIAN_REVERSE enabled | |||||
* and that BAD_OPCODE occurs if disabled. | |||||
*/ | |||||
static void CheckPassIfEnabled(const uint32_t flags, | |||||
const stacktype &original_stack, | |||||
const CScript &script, | |||||
const stacktype &expected) { | |||||
CheckPassWithFlags(flags | SCRIPT_ENABLE_OP_ENDIAN_REVERSE, original_stack, | |||||
script, expected); | |||||
CheckErrorWithFlags(flags & ~SCRIPT_ENABLE_OP_ENDIAN_REVERSE, | |||||
original_stack, script, ScriptError::BAD_OPCODE); | |||||
} | |||||
BOOST_AUTO_TEST_CASE(op_endian_reverse_tests) { | |||||
MMIXLinearCongruentialGenerator lcg; | |||||
for (int i = 0; i < 4096; i++) { | |||||
uint32_t flags = lcg.next(); | |||||
// Empty stack. | |||||
CheckErrorIfEnabled(flags, {}, CScript() << OP_ENDIAN_REVERSE, | |||||
ScriptError::INVALID_STACK_OPERATION); | |||||
// Manual tests. | |||||
CheckPassIfEnabled(flags, {{}}, CScript() << OP_ENDIAN_REVERSE, {{}}); | |||||
CheckPassIfEnabled(flags, {{99}}, CScript() << OP_ENDIAN_REVERSE, | |||||
{{99}}); | |||||
CheckPassIfEnabled(flags, {{0xde, 0xad}}, | |||||
CScript() << OP_ENDIAN_REVERSE, {{0xad, 0xde}}); | |||||
CheckPassIfEnabled(flags, {{0xde, 0xad, 0xa1}}, | |||||
CScript() << OP_ENDIAN_REVERSE, | |||||
{{0xa1, 0xad, 0xde}}); | |||||
CheckPassIfEnabled(flags, {{0xde, 0xad, 0xbe, 0xef}}, | |||||
CScript() << OP_ENDIAN_REVERSE, | |||||
{{0xef, 0xbe, 0xad, 0xde}}); | |||||
CheckPassIfEnabled(flags, {{0x12, 0x34, 0x56}, {0x56, 0x34, 0x12}}, | |||||
CScript() << OP_ENDIAN_REVERSE << OP_EQUALVERIFY, | |||||
{}); | |||||
// Generated tests, sizes 0 to 520 shoud succeed | |||||
for (int32_t datasize = 0; datasize <= (int32_t)MAX_SCRIPT_ELEMENT_SIZE; | |||||
++datasize) { | |||||
valtype data; | |||||
int32_t item; | |||||
data.reserve(datasize); | |||||
for (item = 0; item < datasize; ++item) { | |||||
data.push_back(uint8_t(item % 256)); | |||||
} | |||||
valtype reversed_data(data.rbegin(), data.rend()); | |||||
CheckPassIfEnabled(flags, {data}, CScript() << OP_ENDIAN_REVERSE, | |||||
{reversed_data}); | |||||
} | |||||
// Double reverse -> does nothing. | |||||
CheckPassIfEnabled(flags, {{0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C}}, | |||||
CScript() << OP_DUP << OP_ENDIAN_REVERSE | |||||
<< OP_ENDIAN_REVERSE << OP_EQUALVERIFY, | |||||
{}); | |||||
// Verify palindrome. | |||||
CheckPassIfEnabled( | |||||
flags, {{0x01, 0x02, 0x03, 0x02, 0x01}}, | |||||
CScript() << OP_DUP << OP_ENDIAN_REVERSE << OP_EQUALVERIFY, {}); | |||||
// Verify non-palindrome fails. | |||||
CheckErrorIfEnabled(flags, {{0x01, 0x02, 0x03, 0x02, 0x02}}, | |||||
CScript() << OP_DUP << OP_ENDIAN_REVERSE | |||||
<< OP_EQUALVERIFY, | |||||
ScriptError::EQUALVERIFY); | |||||
} | |||||
} | |||||
BOOST_AUTO_TEST_SUITE_END() |