Skip to content

Commit 3b188b8

Browse files
committed
Merge bitcoin/bitcoin#31576: test: Move script_assets_tests into its own suite
c40dbbb test: Move `script_assets_tests` into its own suite (Hennadii Stepanov) Pull request description: This PR ensures that the `script_assets_tests` test case is explicitly reported as "Skipped" when it is not run, making it clearer when running the test suite with `ctest`: - on the master branch @ 9355578: ``` $ env -u DIR_UNIT_TEST_DATA ctest --test-dir build -j 16 -R "^script_" Internal ctest changing into directory: /home/hebasto/git/bitcoin/build Test project /home/hebasto/git/bitcoin/build Start 87: script_tests Start 83: script_p2sh_tests Start 85: script_segwit_tests Start 86: script_standard_tests Start 84: script_parse_tests 1/5 Test #84: script_parse_tests ............... Passed 0.11 sec 2/5 Test #86: script_standard_tests ............ Passed 0.11 sec 3/5 Test #85: script_segwit_tests .............. Passed 0.12 sec 4/5 Test #83: script_p2sh_tests ................ Passed 0.12 sec 5/5 Test #87: script_tests ..................... Passed 0.36 sec 100% tests passed, 0 tests failed out of 5 Total Test time (real) = 0.37 sec ``` - with this PR: ``` $ env -u DIR_UNIT_TEST_DATA ctest --test-dir build -j 16 -R "^script_" Internal ctest changing into directory: /home/hebasto/git/bitcoin/build Test project /home/hebasto/git/bitcoin/build Start 83: script_assets_tests Start 88: script_tests Start 84: script_p2sh_tests Start 86: script_segwit_tests Start 87: script_standard_tests Start 85: script_parse_tests 1/6 Test #85: script_parse_tests ............... Passed 0.11 sec 2/6 Test #83: script_assets_tests ..............***Skipped 0.12 sec 3/6 Test #86: script_segwit_tests .............. Passed 0.11 sec 4/6 Test #87: script_standard_tests ............ Passed 0.11 sec 5/6 Test #84: script_p2sh_tests ................ Passed 0.12 sec 6/6 Test #88: script_tests ..................... Passed 0.36 sec 100% tests passed, 0 tests failed out of 6 Total Test time (real) = 0.37 sec The following tests did not run: 83 - script_assets_tests (Skipped) $ env DIR_UNIT_TEST_DATA=/home/hebasto/git/bitcoin/qa-assets/unit_test_data ctest --test-dir build -j 16 -R "^script_" Internal ctest changing into directory: /home/hebasto/git/bitcoin/build Test project /home/hebasto/git/bitcoin/build Start 83: script_assets_tests Start 88: script_tests Start 84: script_p2sh_tests Start 86: script_segwit_tests Start 87: script_standard_tests Start 85: script_parse_tests 1/6 Test #85: script_parse_tests ............... Passed 0.11 sec 2/6 Test #87: script_standard_tests ............ Passed 0.11 sec 3/6 Test #86: script_segwit_tests .............. Passed 0.11 sec 4/6 Test #84: script_p2sh_tests ................ Passed 0.12 sec 5/6 Test #88: script_tests ..................... Passed 0.35 sec 6/6 Test #83: script_assets_tests .............. Passed 1.58 sec 100% tests passed, 0 tests failed out of 6 Total Test time (real) = 1.58 sec ``` ACKs for top commit: maflcko: re-ACK c40dbbb 👈 ajtowns: ACK c40dbbb achow101: ACK c40dbbb Tree-SHA512: 25713e1c3b507b6f2a5fecc7b1ea285a6642b906c248769238a58fc0df48489ac5f7606778f9e3653b407b7f1d06563e1554d04321303b350c80eb888500cc5d
2 parents 2e97541 + c40dbbb commit 3b188b8

File tree

3 files changed

+181
-141
lines changed

3 files changed

+181
-141
lines changed

src/test/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ add_executable(test_bitcoin
8383
rpc_tests.cpp
8484
sanity_tests.cpp
8585
scheduler_tests.cpp
86+
script_assets_tests.cpp
8687
script_p2sh_tests.cpp
8788
script_parse_tests.cpp
8889
script_segwit_tests.cpp
@@ -194,7 +195,7 @@ function(add_boost_test source_file)
194195
COMMAND test_bitcoin --run_test=${test_suite_name} --catch_system_error=no --log_level=test_suite -- DEBUG_LOG_OUT
195196
)
196197
set_property(TEST ${test_suite_name} PROPERTY
197-
SKIP_REGULAR_EXPRESSION "no test cases matching filter"
198+
SKIP_REGULAR_EXPRESSION "no test cases matching filter" "skipping script_assets_test"
198199
)
199200
endforeach()
200201
endfunction()

src/test/script_assets_tests.cpp

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// Copyright (c) 2011-present The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <primitives/transaction.h>
6+
#include <script/interpreter.h>
7+
#include <script/script.h>
8+
#include <script/sigcache.h>
9+
#include <script/sign.h>
10+
#include <script/signingprovider.h>
11+
#include <span.h>
12+
#include <streams.h>
13+
#include <test/util/json.h>
14+
#include <util/check.h>
15+
#include <util/fs.h>
16+
#include <util/strencodings.h>
17+
18+
#include <cstdint>
19+
#include <cstdlib>
20+
#include <fstream>
21+
#include <utility>
22+
#include <vector>
23+
24+
#include <boost/test/unit_test.hpp>
25+
26+
#include <univalue.h>
27+
28+
unsigned int ParseScriptFlags(std::string strFlags);
29+
30+
BOOST_AUTO_TEST_SUITE(script_assets_tests)
31+
32+
template <typename T>
33+
CScript ToScript(const T& byte_container)
34+
{
35+
auto span{MakeUCharSpan(byte_container)};
36+
return {span.begin(), span.end()};
37+
}
38+
39+
static CScript ScriptFromHex(const std::string& str)
40+
{
41+
return ToScript(*Assert(TryParseHex(str)));
42+
}
43+
44+
static CMutableTransaction TxFromHex(const std::string& str)
45+
{
46+
CMutableTransaction tx;
47+
SpanReader{ParseHex(str)} >> TX_NO_WITNESS(tx);
48+
return tx;
49+
}
50+
51+
static std::vector<CTxOut> TxOutsFromJSON(const UniValue& univalue)
52+
{
53+
assert(univalue.isArray());
54+
std::vector<CTxOut> prevouts;
55+
for (size_t i = 0; i < univalue.size(); ++i) {
56+
CTxOut txout;
57+
SpanReader{ParseHex(univalue[i].get_str())} >> txout;
58+
prevouts.push_back(std::move(txout));
59+
}
60+
return prevouts;
61+
}
62+
63+
static CScriptWitness ScriptWitnessFromJSON(const UniValue& univalue)
64+
{
65+
assert(univalue.isArray());
66+
CScriptWitness scriptwitness;
67+
for (size_t i = 0; i < univalue.size(); ++i) {
68+
auto bytes = ParseHex(univalue[i].get_str());
69+
scriptwitness.stack.push_back(std::move(bytes));
70+
}
71+
return scriptwitness;
72+
}
73+
74+
static std::vector<unsigned int> AllConsensusFlags()
75+
{
76+
std::vector<unsigned int> ret;
77+
78+
for (unsigned int i = 0; i < 128; ++i) {
79+
unsigned int flag = 0;
80+
if (i & 1) flag |= SCRIPT_VERIFY_P2SH;
81+
if (i & 2) flag |= SCRIPT_VERIFY_DERSIG;
82+
if (i & 4) flag |= SCRIPT_VERIFY_NULLDUMMY;
83+
if (i & 8) flag |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
84+
if (i & 16) flag |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
85+
if (i & 32) flag |= SCRIPT_VERIFY_WITNESS;
86+
if (i & 64) flag |= SCRIPT_VERIFY_TAPROOT;
87+
88+
// SCRIPT_VERIFY_WITNESS requires SCRIPT_VERIFY_P2SH
89+
if (flag & SCRIPT_VERIFY_WITNESS && !(flag & SCRIPT_VERIFY_P2SH)) continue;
90+
// SCRIPT_VERIFY_TAPROOT requires SCRIPT_VERIFY_WITNESS
91+
if (flag & SCRIPT_VERIFY_TAPROOT && !(flag & SCRIPT_VERIFY_WITNESS)) continue;
92+
93+
ret.push_back(flag);
94+
}
95+
96+
return ret;
97+
}
98+
99+
/** Precomputed list of all valid combinations of consensus-relevant script validation flags. */
100+
static const std::vector<unsigned int> ALL_CONSENSUS_FLAGS = AllConsensusFlags();
101+
102+
static void AssetTest(const UniValue& test, SignatureCache& signature_cache)
103+
{
104+
BOOST_CHECK(test.isObject());
105+
106+
CMutableTransaction mtx = TxFromHex(test["tx"].get_str());
107+
const std::vector<CTxOut> prevouts = TxOutsFromJSON(test["prevouts"]);
108+
BOOST_CHECK(prevouts.size() == mtx.vin.size());
109+
size_t idx = test["index"].getInt<int64_t>();
110+
uint32_t test_flags{ParseScriptFlags(test["flags"].get_str())};
111+
bool fin = test.exists("final") && test["final"].get_bool();
112+
113+
if (test.exists("success")) {
114+
mtx.vin[idx].scriptSig = ScriptFromHex(test["success"]["scriptSig"].get_str());
115+
mtx.vin[idx].scriptWitness = ScriptWitnessFromJSON(test["success"]["witness"]);
116+
CTransaction tx(mtx);
117+
PrecomputedTransactionData txdata;
118+
txdata.Init(tx, std::vector<CTxOut>(prevouts));
119+
CachingTransactionSignatureChecker txcheck(&tx, idx, prevouts[idx].nValue, true, signature_cache, txdata);
120+
121+
for (const auto flags : ALL_CONSENSUS_FLAGS) {
122+
// "final": true tests are valid for all flags. Others are only valid with flags that are
123+
// a subset of test_flags.
124+
if (fin || ((flags & test_flags) == flags)) {
125+
bool ret = VerifyScript(tx.vin[idx].scriptSig, prevouts[idx].scriptPubKey, &tx.vin[idx].scriptWitness, flags, txcheck, nullptr);
126+
BOOST_CHECK(ret);
127+
}
128+
}
129+
}
130+
131+
if (test.exists("failure")) {
132+
mtx.vin[idx].scriptSig = ScriptFromHex(test["failure"]["scriptSig"].get_str());
133+
mtx.vin[idx].scriptWitness = ScriptWitnessFromJSON(test["failure"]["witness"]);
134+
CTransaction tx(mtx);
135+
PrecomputedTransactionData txdata;
136+
txdata.Init(tx, std::vector<CTxOut>(prevouts));
137+
CachingTransactionSignatureChecker txcheck(&tx, idx, prevouts[idx].nValue, true, signature_cache, txdata);
138+
139+
for (const auto flags : ALL_CONSENSUS_FLAGS) {
140+
// If a test is supposed to fail with test_flags, it should also fail with any superset thereof.
141+
if ((flags & test_flags) == test_flags) {
142+
bool ret = VerifyScript(tx.vin[idx].scriptSig, prevouts[idx].scriptPubKey, &tx.vin[idx].scriptWitness, flags, txcheck, nullptr);
143+
BOOST_CHECK(!ret);
144+
}
145+
}
146+
}
147+
}
148+
149+
BOOST_AUTO_TEST_CASE(script_assets_test)
150+
{
151+
// See src/test/fuzz/script_assets_test_minimizer.cpp for information on how to generate
152+
// the script_assets_test.json file used by this test.
153+
SignatureCache signature_cache{DEFAULT_SIGNATURE_CACHE_BYTES};
154+
155+
const char* dir = std::getenv("DIR_UNIT_TEST_DATA");
156+
BOOST_WARN_MESSAGE(dir != nullptr, "Variable DIR_UNIT_TEST_DATA unset, skipping script_assets_test");
157+
if (dir == nullptr) return;
158+
auto path = fs::path(dir) / "script_assets_test.json";
159+
bool exists = fs::exists(path);
160+
BOOST_WARN_MESSAGE(exists, "File $DIR_UNIT_TEST_DATA/script_assets_test.json not found, skipping script_assets_test");
161+
if (!exists) return;
162+
std::ifstream file{path};
163+
BOOST_CHECK(file.is_open());
164+
file.seekg(0, std::ios::end);
165+
size_t length = file.tellg();
166+
file.seekg(0, std::ios::beg);
167+
std::string data(length, '\0');
168+
file.read(data.data(), data.size());
169+
UniValue tests = read_json(data);
170+
BOOST_CHECK(tests.isArray());
171+
BOOST_CHECK(tests.size() > 0);
172+
173+
for (size_t i = 0; i < tests.size(); i++) {
174+
AssetTest(tests[i], signature_cache);
175+
}
176+
file.close();
177+
}
178+
179+
BOOST_AUTO_TEST_SUITE_END()

src/test/script_tests.cpp

Lines changed: 0 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,11 +1384,6 @@ CScript ToScript(const T& byte_container)
13841384
return {span.begin(), span.end()};
13851385
}
13861386

1387-
static CScript ScriptFromHex(const std::string& str)
1388-
{
1389-
return ToScript(*Assert(TryParseHex(str)));
1390-
}
1391-
13921387
BOOST_AUTO_TEST_CASE(script_byte_array_u8_vector_equivalence)
13931388
{
13941389
const CScript scriptPubKey1 = CScript() << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"_hex_v_u8 << OP_CHECKSIG;
@@ -1519,141 +1514,6 @@ BOOST_AUTO_TEST_CASE(script_HasValidOps)
15191514
BOOST_CHECK(!script.HasValidOps());
15201515
}
15211516

1522-
static CMutableTransaction TxFromHex(const std::string& str)
1523-
{
1524-
CMutableTransaction tx;
1525-
SpanReader{ParseHex(str)} >> TX_NO_WITNESS(tx);
1526-
return tx;
1527-
}
1528-
1529-
static std::vector<CTxOut> TxOutsFromJSON(const UniValue& univalue)
1530-
{
1531-
assert(univalue.isArray());
1532-
std::vector<CTxOut> prevouts;
1533-
for (size_t i = 0; i < univalue.size(); ++i) {
1534-
CTxOut txout;
1535-
SpanReader{ParseHex(univalue[i].get_str())} >> txout;
1536-
prevouts.push_back(std::move(txout));
1537-
}
1538-
return prevouts;
1539-
}
1540-
1541-
static CScriptWitness ScriptWitnessFromJSON(const UniValue& univalue)
1542-
{
1543-
assert(univalue.isArray());
1544-
CScriptWitness scriptwitness;
1545-
for (size_t i = 0; i < univalue.size(); ++i) {
1546-
auto bytes = ParseHex(univalue[i].get_str());
1547-
scriptwitness.stack.push_back(std::move(bytes));
1548-
}
1549-
return scriptwitness;
1550-
}
1551-
1552-
static std::vector<unsigned int> AllConsensusFlags()
1553-
{
1554-
std::vector<unsigned int> ret;
1555-
1556-
for (unsigned int i = 0; i < 128; ++i) {
1557-
unsigned int flag = 0;
1558-
if (i & 1) flag |= SCRIPT_VERIFY_P2SH;
1559-
if (i & 2) flag |= SCRIPT_VERIFY_DERSIG;
1560-
if (i & 4) flag |= SCRIPT_VERIFY_NULLDUMMY;
1561-
if (i & 8) flag |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
1562-
if (i & 16) flag |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
1563-
if (i & 32) flag |= SCRIPT_VERIFY_WITNESS;
1564-
if (i & 64) flag |= SCRIPT_VERIFY_TAPROOT;
1565-
1566-
// SCRIPT_VERIFY_WITNESS requires SCRIPT_VERIFY_P2SH
1567-
if (flag & SCRIPT_VERIFY_WITNESS && !(flag & SCRIPT_VERIFY_P2SH)) continue;
1568-
// SCRIPT_VERIFY_TAPROOT requires SCRIPT_VERIFY_WITNESS
1569-
if (flag & SCRIPT_VERIFY_TAPROOT && !(flag & SCRIPT_VERIFY_WITNESS)) continue;
1570-
1571-
ret.push_back(flag);
1572-
}
1573-
1574-
return ret;
1575-
}
1576-
1577-
/** Precomputed list of all valid combinations of consensus-relevant script validation flags. */
1578-
static const std::vector<unsigned int> ALL_CONSENSUS_FLAGS = AllConsensusFlags();
1579-
1580-
static void AssetTest(const UniValue& test, SignatureCache& signature_cache)
1581-
{
1582-
BOOST_CHECK(test.isObject());
1583-
1584-
CMutableTransaction mtx = TxFromHex(test["tx"].get_str());
1585-
const std::vector<CTxOut> prevouts = TxOutsFromJSON(test["prevouts"]);
1586-
BOOST_CHECK(prevouts.size() == mtx.vin.size());
1587-
size_t idx = test["index"].getInt<int64_t>();
1588-
uint32_t test_flags{ParseScriptFlags(test["flags"].get_str())};
1589-
bool fin = test.exists("final") && test["final"].get_bool();
1590-
1591-
if (test.exists("success")) {
1592-
mtx.vin[idx].scriptSig = ScriptFromHex(test["success"]["scriptSig"].get_str());
1593-
mtx.vin[idx].scriptWitness = ScriptWitnessFromJSON(test["success"]["witness"]);
1594-
CTransaction tx(mtx);
1595-
PrecomputedTransactionData txdata;
1596-
txdata.Init(tx, std::vector<CTxOut>(prevouts));
1597-
CachingTransactionSignatureChecker txcheck(&tx, idx, prevouts[idx].nValue, true, signature_cache, txdata);
1598-
1599-
for (const auto flags : ALL_CONSENSUS_FLAGS) {
1600-
// "final": true tests are valid for all flags. Others are only valid with flags that are
1601-
// a subset of test_flags.
1602-
if (fin || ((flags & test_flags) == flags)) {
1603-
bool ret = VerifyScript(tx.vin[idx].scriptSig, prevouts[idx].scriptPubKey, &tx.vin[idx].scriptWitness, flags, txcheck, nullptr);
1604-
BOOST_CHECK(ret);
1605-
}
1606-
}
1607-
}
1608-
1609-
if (test.exists("failure")) {
1610-
mtx.vin[idx].scriptSig = ScriptFromHex(test["failure"]["scriptSig"].get_str());
1611-
mtx.vin[idx].scriptWitness = ScriptWitnessFromJSON(test["failure"]["witness"]);
1612-
CTransaction tx(mtx);
1613-
PrecomputedTransactionData txdata;
1614-
txdata.Init(tx, std::vector<CTxOut>(prevouts));
1615-
CachingTransactionSignatureChecker txcheck(&tx, idx, prevouts[idx].nValue, true, signature_cache, txdata);
1616-
1617-
for (const auto flags : ALL_CONSENSUS_FLAGS) {
1618-
// If a test is supposed to fail with test_flags, it should also fail with any superset thereof.
1619-
if ((flags & test_flags) == test_flags) {
1620-
bool ret = VerifyScript(tx.vin[idx].scriptSig, prevouts[idx].scriptPubKey, &tx.vin[idx].scriptWitness, flags, txcheck, nullptr);
1621-
BOOST_CHECK(!ret);
1622-
}
1623-
}
1624-
}
1625-
}
1626-
1627-
BOOST_AUTO_TEST_CASE(script_assets_test)
1628-
{
1629-
// See src/test/fuzz/script_assets_test_minimizer.cpp for information on how to generate
1630-
// the script_assets_test.json file used by this test.
1631-
SignatureCache signature_cache{DEFAULT_SIGNATURE_CACHE_BYTES};
1632-
1633-
const char* dir = std::getenv("DIR_UNIT_TEST_DATA");
1634-
BOOST_WARN_MESSAGE(dir != nullptr, "Variable DIR_UNIT_TEST_DATA unset, skipping script_assets_test");
1635-
if (dir == nullptr) return;
1636-
auto path = fs::path(dir) / "script_assets_test.json";
1637-
bool exists = fs::exists(path);
1638-
BOOST_WARN_MESSAGE(exists, "File $DIR_UNIT_TEST_DATA/script_assets_test.json not found, skipping script_assets_test");
1639-
if (!exists) return;
1640-
std::ifstream file{path};
1641-
BOOST_CHECK(file.is_open());
1642-
file.seekg(0, std::ios::end);
1643-
size_t length = file.tellg();
1644-
file.seekg(0, std::ios::beg);
1645-
std::string data(length, '\0');
1646-
file.read(data.data(), data.size());
1647-
UniValue tests = read_json(data);
1648-
BOOST_CHECK(tests.isArray());
1649-
BOOST_CHECK(tests.size() > 0);
1650-
1651-
for (size_t i = 0; i < tests.size(); i++) {
1652-
AssetTest(tests[i], signature_cache);
1653-
}
1654-
file.close();
1655-
}
1656-
16571517
BOOST_AUTO_TEST_CASE(bip341_keypath_test_vectors)
16581518
{
16591519
UniValue tests;

0 commit comments

Comments
 (0)