Changeset View
Changeset View
Standalone View
Standalone View
src/test/bswap_tests.cpp
// Copyright (c) 2018 The Bitcoin developers | // Copyright (c) 2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <policy/policy.h> | #include <compat/byteswap.h> | ||||
#include <script/interpreter.h> | |||||
#include <test/lcg.h> | |||||
#include <test/test_bitcoin.h> | #include <test/test_bitcoin.h> | ||||
#include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||
#include <array> | |||||
#include <bitset> | |||||
typedef std::vector<uint8_t> valtype; | |||||
typedef std::vector<valtype> stacktype; | |||||
BOOST_FIXTURE_TEST_SUITE(bswap_tests, BasicTestingSetup) | BOOST_FIXTURE_TEST_SUITE(bswap_tests, BasicTestingSetup) | ||||
std::array<uint32_t, 3> flagset{{0, STANDARD_SCRIPT_VERIFY_FLAGS}}; | BOOST_AUTO_TEST_CASE(bswap_tests) { | ||||
// Sibling in bitcoin/src/qt/test/compattests.cpp | |||||
static void CheckError(uint32_t flags, const stacktype &original_stack, | uint16_t u1 = 0x1234; | ||||
const CScript &script, ScriptError expected) { | uint32_t u2 = 0x56789abc; | ||||
BaseSignatureChecker sigchecker; | uint64_t u3 = 0xdef0123456789abc; | ||||
ScriptError err = ScriptError::OK; | uint16_t e1 = 0x3412; | ||||
stacktype stack{original_stack}; | uint32_t e2 = 0xbc9a7856; | ||||
bool r = EvalScript(stack, script, flags, sigchecker, &err); | uint64_t e3 = 0xbc9a78563412f0de; | ||||
BOOST_CHECK(!r); | BOOST_CHECK(bswap_16(u1) == e1); | ||||
BOOST_CHECK(err == expected); | BOOST_CHECK(bswap_32(u2) == e2); | ||||
} | BOOST_CHECK(bswap_64(u3) == e3); | ||||
static void CheckPass(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); | |||||
} | |||||
/** | |||||
* General utility functions to check for script passing/failing. | |||||
*/ | |||||
static void CheckErrorForAllFlags(const stacktype &original_stack, | |||||
const CScript &script, ScriptError expected) { | |||||
for (uint32_t flags : flagset) { | |||||
// The script generates the proper error regardless of whether or not | |||||
// SCRIPT_ENABLE_OP_BSWAP flag is passed. | |||||
CheckError(flags & ~SCRIPT_ENABLE_OP_BSWAP, original_stack, script, | |||||
expected); | |||||
CheckError(flags | SCRIPT_ENABLE_OP_BSWAP, original_stack, script, | |||||
expected); | |||||
} | |||||
} | |||||
BOOST_AUTO_TEST_CASE(bswap_test) { | |||||
// Opcode not enabled. | |||||
CheckError(STANDARD_SCRIPT_VERIFY_FLAGS & ~SCRIPT_ENABLE_OP_BSWAP, {}, | |||||
CScript() << OP_BSWAP, ScriptError::BAD_OPCODE); | |||||
// Empty stack. | |||||
CheckError(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OP_BSWAP, {}, | |||||
CScript() << OP_BSWAP, ScriptError::INVALID_STACK_OPERATION); | |||||
// Manual tests. | |||||
CheckPass(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OP_BSWAP, {{}}, | |||||
CScript() << OP_BSWAP, {{}}); | |||||
CheckPass(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OP_BSWAP, {{99}}, | |||||
CScript() << OP_BSWAP, {{99}}); | |||||
CheckPass(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OP_BSWAP, | |||||
{{0xde, 0xad}}, CScript() << OP_BSWAP, {{0xad, 0xde}}); | |||||
CheckPass(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OP_BSWAP, | |||||
{{0xde, 0xad, 0xa1}}, CScript() << OP_BSWAP, | |||||
{{0xa1, 0xad, 0xde}}); | |||||
CheckPass(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OP_BSWAP, | |||||
{{0xde, 0xad, 0xbe, 0xef}}, CScript() << OP_BSWAP, | |||||
{{0xef, 0xbe, 0xad, 0xde}}); | |||||
// Generated tests, sizes 0 to 520 that shoud succeed | |||||
// + 20 that should fail. | |||||
for (size_t datasize = 0; datasize <= 520 + 20; ++datasize) { | |||||
valtype data; | |||||
data.reserve(datasize); | |||||
for (uint8_t item = 0; item < (uint8_t)datasize; ++item) { | |||||
data.push_back(item); | |||||
} | |||||
if (datasize <= 520) { | |||||
valtype reversed_data; | |||||
reversed_data.reserve(datasize); | |||||
for (uint8_t item = (uint8_t)datasize - 1; item >= 0; --item) { | |||||
reversed_data.push_back(item); | |||||
} | |||||
CheckPass(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OP_BSWAP, | |||||
{data}, CScript() << OP_BSWAP, {reversed_data}); | |||||
} else { | |||||
CheckErrorForAllFlags({data}, CScript() << OP_BSWAP, | |||||
ScriptError::PUSH_SIZE); | |||||
} | |||||
} | |||||
// More tests. | |||||
CheckPass(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OP_BSWAP, | |||||
{{0x12, 0x34, 0x56}, {0x56, 0x34, 0x12}}, | |||||
CScript() << OP_BSWAP << OP_EQUALVERIFY, {}); | |||||
CheckPass(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OP_BSWAP, | |||||
{{0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C}}, | |||||
CScript() << OP_DUP << OP_BSWAP << OP_BSWAP << OP_EQUALVERIFY, | |||||
{}); | |||||
// Verify palindrome. | |||||
CheckPass(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OP_BSWAP, | |||||
{{0x01, 0x02, 0x03, 0x02, 0x01}}, | |||||
CScript() << OP_DUP << OP_BSWAP << OP_EQUALVERIFY, {}); | |||||
// Verify non-palindrome fails. | |||||
CheckError(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OP_BSWAP, | |||||
{{0x01, 0x02, 0x03, 0x02, 0x02}}, | |||||
CScript() << OP_DUP << OP_BSWAP << OP_EQUALVERIFY, | |||||
ScriptError::EQUALVERIFY); | |||||
} | } | ||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |