script_flags.cpp raw
1 // Copyright (c) 2009-2021 The Limenka 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 <consensus/amount.h>
6 #include <primitives/transaction.h>
7 #include <script/interpreter.h>
8 #include <serialize.h>
9 #include <streams.h>
10 #include <test/fuzz/fuzz.h>
11 #include <test/util/script.h>
12
13 #include <cassert>
14 #include <ios>
15 #include <utility>
16 #include <vector>
17
18 FUZZ_TARGET(script_flags)
19 {
20 if (buffer.size() > 100'000) return;
21 DataStream ds{buffer};
22 try {
23 const CTransaction tx(deserialize, TX_WITH_WITNESS, ds);
24
25 unsigned int verify_flags;
26 ds >> verify_flags;
27
28 if (!IsValidFlagCombination(verify_flags)) return;
29
30 unsigned int fuzzed_flags;
31 ds >> fuzzed_flags;
32
33 std::vector<CTxOut> spent_outputs;
34 for (unsigned i = 0; i < tx.vin.size(); ++i) {
35 CTxOut prevout;
36 ds >> prevout;
37 if (!MoneyRange(prevout.nValue)) {
38 // prevouts should be consensus-valid
39 prevout.nValue = 1;
40 }
41 spent_outputs.push_back(prevout);
42 }
43 PrecomputedTransactionData txdata;
44 txdata.Init(tx, std::move(spent_outputs));
45
46 for (unsigned i = 0; i < tx.vin.size(); ++i) {
47 const CTxOut& prevout = txdata.m_spent_outputs.at(i);
48 const TransactionSignatureChecker checker{&tx, i, prevout.nValue, txdata, MissingDataBehavior::ASSERT_FAIL};
49
50 ScriptError serror;
51 const bool ret = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror);
52 assert(ret == (serror == SCRIPT_ERR_OK));
53
54 // Verify that removing flags from a passing test or adding flags to a failing test does not change the result
55 if (ret) {
56 verify_flags &= ~fuzzed_flags;
57 } else {
58 verify_flags |= fuzzed_flags;
59 }
60 if (!IsValidFlagCombination(verify_flags)) return;
61
62 ScriptError serror_fuzzed;
63 const bool ret_fuzzed = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror_fuzzed);
64 assert(ret_fuzzed == (serror_fuzzed == SCRIPT_ERR_OK));
65
66 assert(ret_fuzzed == ret);
67 }
68 } catch (const std::ios_base::failure&) {
69 return;
70 }
71 }
72