Line data Source code
1 : // Copyright (c) 2011-2021 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 <test/data/tx_invalid.json.h>
6 : #include <test/data/tx_valid.json.h>
7 : #include <test/util/setup_common.h>
8 :
9 : #include <checkqueue.h>
10 : #include <clientversion.h>
11 : #include <consensus/tx_check.h>
12 : #include <consensus/validation.h>
13 : #include <core_io.h>
14 : #include <key.h>
15 : #include <policy/policy.h>
16 : #include <policy/settings.h>
17 : #include <script/script.h>
18 : #include <script/script_error.h>
19 : #include <script/signingprovider.h>
20 : #include <streams.h>
21 : #include <test/util/json.h>
22 : #include <test/util/random.h>
23 : #include <test/util/transaction_utils.h>
24 : #include <util/strencodings.h>
25 : #include <util/string.h>
26 : #include <validation.h>
27 :
28 : #include <functional>
29 : #include <map>
30 : #include <string>
31 :
32 : #include <boost/test/unit_test.hpp>
33 :
34 : #include <univalue.h>
35 :
36 146 : static std::map<std::string, unsigned int> mapFlagNames = {
37 146 : {std::string("P2SH"), (unsigned int) SCRIPT_VERIFY_P2SH},
38 146 : {std::string("STRICTENC"), (unsigned int) SCRIPT_VERIFY_STRICTENC},
39 146 : {std::string("DERSIG"), (unsigned int) SCRIPT_VERIFY_DERSIG},
40 146 : {std::string("LOW_S"), (unsigned int) SCRIPT_VERIFY_LOW_S},
41 146 : {std::string("SIGPUSHONLY"), (unsigned int) SCRIPT_VERIFY_SIGPUSHONLY},
42 146 : {std::string("MINIMALDATA"), (unsigned int) SCRIPT_VERIFY_MINIMALDATA},
43 146 : {std::string("NULLDUMMY"), (unsigned int) SCRIPT_VERIFY_NULLDUMMY},
44 146 : {std::string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int) SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS},
45 146 : {std::string("CLEANSTACK"), (unsigned int) SCRIPT_VERIFY_CLEANSTACK},
46 146 : {std::string("NULLFAIL"), (unsigned int) SCRIPT_VERIFY_NULLFAIL},
47 146 : {std::string("CHECKLOCKTIMEVERIFY"), (unsigned int) SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY},
48 146 : {std::string("CHECKSEQUENCEVERIFY"), (unsigned int) SCRIPT_VERIFY_CHECKSEQUENCEVERIFY},
49 146 : {std::string("CONST_SCRIPTCODE"), (unsigned int)SCRIPT_VERIFY_CONST_SCRIPTCODE},
50 : };
51 :
52 1431 : unsigned int ParseScriptFlags(std::string strFlags)
53 : {
54 1431 : if (strFlags.empty() || strFlags == "NONE") return 0;
55 1273 : unsigned int flags = 0;
56 1273 : std::vector<std::string> words = SplitString(strFlags, ',');
57 :
58 3631 : for (const std::string& word : words)
59 : {
60 2358 : if (!mapFlagNames.count(word))
61 0 : BOOST_ERROR("Bad test: unknown verification flag '" << word << "'");
62 2358 : flags |= mapFlagNames[word];
63 : }
64 :
65 1273 : return flags;
66 1431 : }
67 :
68 106 : std::string FormatScriptFlags(unsigned int flags)
69 : {
70 106 : if (flags == 0) {
71 41 : return "";
72 : }
73 65 : std::string ret;
74 65 : std::map<std::string, unsigned int>::const_iterator it = mapFlagNames.begin();
75 910 : while (it != mapFlagNames.end()) {
76 845 : if (flags & it->second) {
77 86 : ret += it->first + ",";
78 86 : }
79 845 : it++;
80 : }
81 65 : return ret.substr(0, ret.size() - 1);
82 106 : }
83 :
84 : /*
85 : * Check that the input scripts of a transaction are valid/invalid as expected.
86 : */
87 4023 : bool CheckTxScripts(const CTransaction& tx, const std::map<COutPoint, CScript>& map_prevout_scriptPubKeys,
88 : unsigned int flags,
89 : const PrecomputedTransactionData& txdata, const std::string& strTest, bool expect_valid)
90 : {
91 4023 : bool tx_valid = true;
92 4023 : ScriptError err = expect_valid ? SCRIPT_ERR_UNKNOWN_ERROR : SCRIPT_ERR_OK;
93 8316 : for (unsigned int i = 0; i < tx.vin.size() && tx_valid; ++i) {
94 4293 : const CTxIn input = tx.vin[i];
95 4293 : const CAmount amount = 0;
96 : try {
97 8586 : tx_valid = VerifyScript(input.scriptSig, map_prevout_scriptPubKeys.at(input.prevout),
98 4293 : flags, TransactionSignatureChecker(&tx, i, amount, txdata, MissingDataBehavior::ASSERT_FAIL), &err);
99 4293 : } catch (...) {
100 0 : BOOST_ERROR("Bad test: " << strTest);
101 0 : return true; // The test format is bad and an error is thrown. Return true to silence further error.
102 0 : }
103 4293 : if (expect_valid) {
104 2457 : BOOST_CHECK_MESSAGE(tx_valid, strTest);
105 2457 : BOOST_CHECK_MESSAGE((err == SCRIPT_ERR_OK), ScriptErrorString(err));
106 2457 : err = SCRIPT_ERR_UNKNOWN_ERROR;
107 2457 : }
108 4293 : }
109 4023 : if (!expect_valid) {
110 1782 : BOOST_CHECK_MESSAGE(!tx_valid, strTest);
111 1782 : BOOST_CHECK_MESSAGE((err != SCRIPT_ERR_OK), ScriptErrorString(err));
112 1782 : }
113 4023 : return (tx_valid == expect_valid);
114 4023 : }
115 :
116 : /*
117 : * Trim or fill flags to make the combination valid, used for SegWit code only
118 : */
119 :
120 4095 : unsigned int TrimFlags(unsigned int flags)
121 : {
122 : // CLEANSTACK requires P2SH)
123 4095 : if (!(flags & SCRIPT_VERIFY_P2SH)) flags &= ~(unsigned int)SCRIPT_VERIFY_CLEANSTACK;
124 :
125 4095 : return flags;
126 : }
127 :
128 1799 : unsigned int FillFlags(unsigned int flags)
129 : {
130 : // CLEANSTACK implies P2SH
131 1799 : if (flags & SCRIPT_VERIFY_CLEANSTACK) flags |= SCRIPT_VERIFY_P2SH;
132 :
133 1799 : return flags;
134 : }
135 :
136 : // Return valid flags that are all except one flag for each flag
137 149 : std::vector<unsigned int> ExcludeIndividualFlags(unsigned int flags)
138 : {
139 149 : std::vector<unsigned int> flags_combos;
140 2086 : for (unsigned int i = 0; i < mapFlagNames.size(); ++i) {
141 1937 : const unsigned int flags_excluding_i = TrimFlags(flags & ~(1U << i));
142 1937 : if (flags != flags_excluding_i && std::find(flags_combos.begin(), flags_combos.end(), flags_excluding_i) != flags_combos.end()) {
143 0 : flags_combos.push_back(flags_excluding_i);
144 0 : }
145 1937 : }
146 149 : return flags_combos;
147 149 : }
148 :
149 146 : BOOST_FIXTURE_TEST_SUITE(transaction_tests, BasicTestingSetup)
150 :
151 149 : BOOST_AUTO_TEST_CASE(tx_valid)
152 : {
153 : // Read tests from test/data/tx_valid.json
154 1 : UniValue tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid)));
155 :
156 163 : for (unsigned int idx = 0; idx < tests.size(); idx++) {
157 162 : const UniValue& test = tests[idx];
158 162 : std::string strTest = test.write();
159 162 : if (test[0].isArray())
160 : {
161 83 : if (test.size() != 3 || !test[1].isStr() || !test[2].isStr())
162 : {
163 0 : BOOST_ERROR("Bad test: " << strTest);
164 0 : continue;
165 : }
166 :
167 83 : std::map<COutPoint, CScript> mapprevOutScriptPubKeys;
168 83 : UniValue inputs = test[0].get_array();
169 83 : bool fValid = true;
170 174 : for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
171 91 : const UniValue& input = inputs[inpIdx];
172 91 : if (!input.isArray()) {
173 0 : fValid = false;
174 0 : break;
175 : }
176 91 : const UniValue& vinput = input.get_array();
177 91 : if (vinput.size() != 3)
178 : {
179 0 : fValid = false;
180 0 : break;
181 : }
182 :
183 91 : mapprevOutScriptPubKeys[COutPoint{uint256S(vinput[0].get_str()), uint32_t(vinput[1].getInt<int>())}] = ParseScript(vinput[2].get_str());
184 91 : }
185 83 : if (!fValid)
186 : {
187 0 : BOOST_ERROR("Bad test: " << strTest);
188 0 : continue;
189 : }
190 :
191 83 : std::string transaction = test[1].get_str();
192 83 : CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
193 83 : CTransaction tx(deserialize, stream);
194 :
195 83 : TxValidationState state;
196 83 : BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest);
197 83 : BOOST_CHECK(state.IsValid());
198 :
199 83 : PrecomputedTransactionData txdata(tx);
200 83 : unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
201 :
202 : // Check that the test gives a valid combination of flags (otherwise VerifyScript will throw). Don't edit the flags.
203 83 : if (~verify_flags != FillFlags(~verify_flags)) {
204 0 : BOOST_ERROR("Bad test flags: " << strTest);
205 0 : }
206 :
207 83 : if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, ~verify_flags, txdata, strTest, /*expect_valid=*/true)) {
208 0 : BOOST_ERROR("Tx unexpectedly failed: " << strTest);
209 0 : }
210 :
211 : // Backwards compatibility of script verification flags: Removing any flag(s) should not invalidate a valid transaction
212 1162 : for (size_t i = 0; i < mapFlagNames.size(); ++i) {
213 : // Removing individual flags
214 1079 : unsigned int flags = TrimFlags(~(verify_flags | (1U << i)));
215 1079 : if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, flags, txdata, strTest, /*expect_valid=*/true)) {
216 0 : BOOST_ERROR("Tx unexpectedly failed with flag " << ToString(i) << " unset: " << strTest);
217 0 : }
218 : // Removing random combinations of flags
219 1079 : flags = TrimFlags(~(verify_flags | (unsigned int)InsecureRandBits(mapFlagNames.size())));
220 1079 : if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, flags, txdata, strTest, /*expect_valid=*/true)) {
221 0 : BOOST_ERROR("Tx unexpectedly failed with random flags " << ToString(flags) << ": " << strTest);
222 0 : }
223 1079 : }
224 :
225 : // Check that flags are maximal: transaction should fail if any unset flags are set.
226 83 : for (auto flags_excluding_one: ExcludeIndividualFlags(verify_flags)) {
227 0 : if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, ~flags_excluding_one, txdata, strTest, /*expect_valid=*/false)) {
228 0 : BOOST_ERROR("Too many flags unset: " << strTest);
229 0 : }
230 : }
231 83 : }
232 162 : }
233 1 : }
234 :
235 149 : BOOST_AUTO_TEST_CASE(tx_invalid)
236 : {
237 : // Read tests from test/data/tx_invalid.json
238 1 : UniValue tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid)));
239 :
240 155 : for (unsigned int idx = 0; idx < tests.size(); idx++) {
241 154 : const UniValue& test = tests[idx];
242 154 : std::string strTest = test.write();
243 154 : if (test[0].isArray())
244 : {
245 76 : if (test.size() != 3 || !test[1].isStr() || !test[2].isStr())
246 : {
247 0 : BOOST_ERROR("Bad test: " << strTest);
248 0 : continue;
249 : }
250 :
251 76 : std::map<COutPoint, CScript> mapprevOutScriptPubKeys;
252 76 : UniValue inputs = test[0].get_array();
253 76 : bool fValid = true;
254 158 : for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
255 82 : const UniValue& input = inputs[inpIdx];
256 82 : if (!input.isArray()) {
257 0 : fValid = false;
258 0 : break;
259 : }
260 82 : const UniValue& vinput = input.get_array();
261 82 : if (vinput.size() != 3)
262 : {
263 0 : fValid = false;
264 0 : break;
265 : }
266 :
267 82 : mapprevOutScriptPubKeys[COutPoint{uint256S(vinput[0].get_str()), uint32_t(vinput[1].getInt<int>())}] = ParseScript(vinput[2].get_str());
268 82 : }
269 76 : if (!fValid)
270 : {
271 0 : BOOST_ERROR("Bad test: " << strTest);
272 0 : continue;
273 : }
274 :
275 76 : std::string transaction = test[1].get_str();
276 76 : CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
277 76 : CTransaction tx(deserialize, stream);
278 :
279 76 : TxValidationState state;
280 76 : if (!CheckTransaction(tx, state) || state.IsInvalid()) {
281 10 : BOOST_CHECK_MESSAGE(test[2].get_str() == "BADTX", strTest);
282 10 : continue;
283 : }
284 :
285 66 : PrecomputedTransactionData txdata(tx);
286 66 : unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
287 :
288 : // Not using FillFlags() in the main test, in order to detect invalid verifyFlags combination
289 66 : if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, verify_flags, txdata, strTest, /*expect_valid=*/false)) {
290 0 : BOOST_ERROR("Tx unexpectedly passed: " << strTest);
291 0 : }
292 :
293 : // Backwards compatibility of script verification flags: Adding any flag(s) should not validate an invalid transaction
294 924 : for (size_t i = 0; i < mapFlagNames.size(); i++) {
295 858 : unsigned int flags = FillFlags(verify_flags | (1U << i));
296 : // Adding individual flags
297 858 : if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, flags, txdata, strTest, /*expect_valid=*/false)) {
298 0 : BOOST_ERROR("Tx unexpectedly passed with flag " << ToString(i) << " set: " << strTest);
299 0 : }
300 : // Adding random combinations of flags
301 858 : flags = FillFlags(verify_flags | (unsigned int)InsecureRandBits(mapFlagNames.size()));
302 858 : if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, flags, txdata, strTest, /*expect_valid=*/false)) {
303 0 : BOOST_ERROR("Tx unexpectedly passed with random flags " << ToString(flags) << ": " << strTest);
304 0 : }
305 858 : }
306 :
307 : // Check that flags are minimal: transaction should succeed if any set flags are unset.
308 66 : for (auto flags_excluding_one: ExcludeIndividualFlags(verify_flags)) {
309 0 : if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, flags_excluding_one, txdata, strTest, /*expect_valid=*/true)) {
310 0 : BOOST_ERROR("Too many flags set: " << strTest);
311 0 : }
312 : }
313 76 : }
314 154 : }
315 1 : }
316 :
317 149 : BOOST_AUTO_TEST_CASE(basic_transaction_tests)
318 : {
319 : // Random real transaction (e2769b09e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436)
320 1 : unsigned char ch[] = {0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f, 0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6, 0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27, 0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f, 0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce, 0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57, 0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0, 0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c, 0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00, 0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e, 0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27, 0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01, 0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10, 0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9, 0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5, 0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff, 0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf, 0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9, 0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb, 0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b, 0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07, 0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0, 0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51, 0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70, 0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00};
321 1 : std::vector<unsigned char> vch(ch, ch + sizeof(ch) -1);
322 1 : CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
323 1 : CMutableTransaction tx;
324 1 : stream >> tx;
325 1 : TxValidationState state;
326 2 : BOOST_CHECK_MESSAGE(CheckTransaction(CTransaction(tx), state) && state.IsValid(), "Simple deserialized transaction should be valid.");
327 :
328 : // Check that duplicate txins fail
329 1 : tx.vin.push_back(tx.vin[0]);
330 1 : BOOST_CHECK_MESSAGE(!CheckTransaction(CTransaction(tx), state) || !state.IsValid(), "Transaction with duplicate txins should be invalid.");
331 1 : }
332 :
333 149 : BOOST_AUTO_TEST_CASE(test_Get)
334 : {
335 1 : FillableSigningProvider keystore;
336 1 : CCoinsView coinsDummy;
337 1 : CCoinsViewCache coins(&coinsDummy);
338 : std::vector<CMutableTransaction> dummyTransactions =
339 1 : SetupDummyInputs(keystore, coins, {11*CENT, 50*CENT, 21*CENT, 22*CENT});
340 :
341 1 : CMutableTransaction t1;
342 1 : t1.vin.resize(3);
343 1 : t1.vin[0].prevout.hash = dummyTransactions[0].GetHash();
344 1 : t1.vin[0].prevout.n = 1;
345 1 : t1.vin[0].scriptSig << std::vector<unsigned char>(65, 0);
346 1 : t1.vin[1].prevout.hash = dummyTransactions[1].GetHash();
347 1 : t1.vin[1].prevout.n = 0;
348 1 : t1.vin[1].scriptSig << std::vector<unsigned char>(65, 0) << std::vector<unsigned char>(33, 4);
349 1 : t1.vin[2].prevout.hash = dummyTransactions[1].GetHash();
350 1 : t1.vin[2].prevout.n = 1;
351 1 : t1.vin[2].scriptSig << std::vector<unsigned char>(65, 0) << std::vector<unsigned char>(33, 4);
352 1 : t1.vout.resize(2);
353 1 : t1.vout[0].nValue = 90*CENT;
354 1 : t1.vout[0].scriptPubKey << OP_1;
355 :
356 1 : BOOST_CHECK(AreInputsStandard(CTransaction(t1), coins));
357 1 : }
358 :
359 149 : BOOST_AUTO_TEST_CASE(test_IsStandard)
360 : {
361 1 : LOCK(cs_main);
362 1 : FillableSigningProvider keystore;
363 1 : CCoinsView coinsDummy;
364 1 : CCoinsViewCache coins(&coinsDummy);
365 : std::vector<CMutableTransaction> dummyTransactions =
366 1 : SetupDummyInputs(keystore, coins, {11*CENT, 50*CENT, 21*CENT, 22*CENT});
367 :
368 1 : CMutableTransaction t;
369 1 : t.vin.resize(1);
370 1 : t.vin[0].prevout.hash = dummyTransactions[0].GetHash();
371 1 : t.vin[0].prevout.n = 1;
372 1 : t.vin[0].scriptSig << std::vector<unsigned char>(65, 0);
373 1 : t.vout.resize(1);
374 1 : t.vout[0].nValue = 90*CENT;
375 1 : CKey key = GenerateRandomKey();
376 1 : t.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
377 :
378 21 : constexpr auto CheckIsStandard = [](const auto& t) {
379 20 : std::string reason;
380 20 : BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
381 20 : BOOST_CHECK(reason.empty());
382 20 : };
383 79 : constexpr auto CheckIsNotStandard = [](const auto& t, const std::string& reason_in) {
384 78 : std::string reason;
385 78 : BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
386 78 : BOOST_CHECK_EQUAL(reason_in, reason);
387 78 : };
388 :
389 1 : CheckIsStandard(t);
390 :
391 : // Check dust with default relay fee:
392 1 : CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK() / 1000;
393 1 : BOOST_CHECK_EQUAL(nDustThreshold, 546);
394 : // dust:
395 1 : t.vout[0].nValue = nDustThreshold - 1;
396 1 : CheckIsNotStandard(t, "dust");
397 : // not dust:
398 1 : t.vout[0].nValue = nDustThreshold;
399 1 : CheckIsStandard(t);
400 :
401 : // Disallowed nVersion
402 1 : t.nVersion = -1;
403 1 : CheckIsNotStandard(t, "version");
404 :
405 1 : t.nVersion = 0;
406 1 : CheckIsNotStandard(t, "version");
407 :
408 1 : t.nVersion = 4;
409 1 : CheckIsNotStandard(t, "version");
410 :
411 : // Allowed nVersion
412 1 : t.nVersion = 1;
413 1 : CheckIsStandard(t);
414 :
415 1 : t.nVersion = 2;
416 1 : CheckIsStandard(t);
417 :
418 1 : t.nVersion = 3;
419 1 : CheckIsStandard(t);
420 : // Check dust with odd relay fee to verify rounding:
421 : // nDustThreshold = 182 * 3702 / 1000
422 1 : minRelayTxFee = CFeeRate(3702);
423 : // dust:
424 1 : t.vout[0].nValue = 546 - 1;
425 1 : CheckIsNotStandard(t, "dust");
426 : // not dust:
427 1 : t.vout[0].nValue = 546;
428 1 : CheckIsStandard(t);
429 1 : minRelayTxFee = CFeeRate(DUST_RELAY_TX_FEE);
430 :
431 1 : t.vout[0].scriptPubKey = CScript() << OP_1;
432 1 : CheckIsNotStandard(t, "scriptpubkey");
433 :
434 : // MAX_OP_RETURN_RELAY-byte TxoutType::NULL_DATA (standard)
435 1 : t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
436 1 : BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY, t.vout[0].scriptPubKey.size());
437 1 : CheckIsStandard(t);
438 :
439 : // MAX_OP_RETURN_RELAY+1-byte TxoutType::NULL_DATA (non-standard)
440 1 : t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800");
441 1 : BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size());
442 1 : CheckIsNotStandard(t, "scriptpubkey");
443 :
444 : // Data payload can be encoded in any way...
445 1 : t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("");
446 1 : CheckIsStandard(t);
447 1 : t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("00") << ParseHex("01");
448 1 : CheckIsStandard(t);
449 : // OP_RESERVED *is* considered to be a PUSHDATA type opcode by IsPushOnly()!
450 1 : t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RESERVED << -1 << 0 << ParseHex("01") << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10 << 11 << 12 << 13 << 14 << 15 << 16;
451 1 : CheckIsStandard(t);
452 1 : t.vout[0].scriptPubKey = CScript() << OP_RETURN << 0 << ParseHex("01") << 2 << ParseHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
453 1 : CheckIsStandard(t);
454 :
455 : // ...so long as it only contains PUSHDATA's
456 1 : t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RETURN;
457 1 : CheckIsNotStandard(t, "scriptpubkey");
458 :
459 : // TxoutType::NULL_DATA w/o PUSHDATA
460 1 : t.vout.resize(1);
461 1 : t.vout[0].scriptPubKey = CScript() << OP_RETURN;
462 1 : CheckIsStandard(t);
463 :
464 : // Only one TxoutType::NULL_DATA permitted in all cases
465 1 : t.vout.resize(2);
466 1 : t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
467 1 : t.vout[0].nValue = 0;
468 1 : t.vout[1].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
469 1 : t.vout[1].nValue = 0;
470 1 : CheckIsNotStandard(t, "multi-op-return");
471 :
472 1 : t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
473 1 : t.vout[1].scriptPubKey = CScript() << OP_RETURN;
474 1 : CheckIsNotStandard(t, "multi-op-return");
475 :
476 1 : t.vout[0].scriptPubKey = CScript() << OP_RETURN;
477 1 : t.vout[1].scriptPubKey = CScript() << OP_RETURN;
478 1 : CheckIsNotStandard(t, "multi-op-return");
479 :
480 : // Check large scriptSig (non-standard if size is >1650 bytes)
481 1 : t.vout.resize(1);
482 1 : t.vout[0].nValue = MAX_MONEY;
483 1 : t.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
484 : // OP_PUSHDATA2 with len (3 bytes) + data (1647 bytes) = 1650 bytes
485 1 : t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(1647, 0); // 1650
486 1 : CheckIsStandard(t);
487 :
488 1 : t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(1648, 0); // 1651
489 1 : CheckIsNotStandard(t, "scriptsig-size");
490 :
491 : // Check scriptSig format (non-standard if there are any other ops than just PUSHs)
492 2 : t.vin[0].scriptSig = CScript()
493 1 : << OP_TRUE << OP_0 << OP_1NEGATE << OP_16 // OP_n (single byte pushes: n = 1, 0, -1, 16)
494 1 : << std::vector<unsigned char>(75, 0) // OP_PUSHx [...x bytes...]
495 1 : << std::vector<unsigned char>(235, 0) // OP_PUSHDATA1 x [...x bytes...]
496 1 : << std::vector<unsigned char>(1234, 0) // OP_PUSHDATA2 x [...x bytes...]
497 1 : << OP_9;
498 1 : CheckIsStandard(t);
499 :
500 1 : const std::vector<unsigned char> non_push_ops = { // arbitrary set of non-push operations
501 : OP_NOP, OP_VERIFY, OP_IF, OP_ROT, OP_3DUP, OP_SIZE, OP_EQUAL, OP_ADD, OP_SUB,
502 : OP_HASH256, OP_CODESEPARATOR, OP_CHECKSIG, OP_CHECKLOCKTIMEVERIFY };
503 :
504 1 : CScript::const_iterator pc = t.vin[0].scriptSig.begin();
505 9 : while (pc < t.vin[0].scriptSig.end()) {
506 : opcodetype opcode;
507 8 : CScript::const_iterator prev_pc = pc;
508 8 : t.vin[0].scriptSig.GetOp(pc, opcode); // advance to next op
509 : // for the sake of simplicity, we only replace single-byte push operations
510 8 : if (opcode >= 1 && opcode <= OP_PUSHDATA4)
511 3 : continue;
512 :
513 5 : int index = prev_pc - t.vin[0].scriptSig.begin();
514 5 : unsigned char orig_op = *prev_pc; // save op
515 : // replace current push-op with each non-push-op
516 70 : for (auto op : non_push_ops) {
517 65 : t.vin[0].scriptSig[index] = op;
518 65 : CheckIsNotStandard(t, "scriptsig-not-pushonly");
519 : }
520 5 : t.vin[0].scriptSig[index] = orig_op; // restore op
521 5 : CheckIsStandard(t);
522 : }
523 :
524 : // Check bare multisig (standard if policy flag fIsBareMultisigStd is set)
525 1 : fIsBareMultisigStd = true;
526 1 : t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1
527 1 : t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);
528 1 : CheckIsStandard(t);
529 :
530 1 : fIsBareMultisigStd = false;
531 1 : CheckIsNotStandard(t, "bare-multisig");
532 1 : fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
533 1 : }
534 :
535 146 : BOOST_AUTO_TEST_SUITE_END()
|