/root/bitcoin/src/test/fuzz/script_flags.cpp
Line | Count | Source |
1 | | // Copyright (c) 2009-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 <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 | | static SpanReader& operator>>(SpanReader& ds, script_verify_flags& f) |
19 | 0 | { |
20 | 0 | script_verify_flags::value_type n{0}; |
21 | 0 | ds >> n; |
22 | 0 | f = script_verify_flags::from_int(n); |
23 | 0 | assert(n == f.as_int()); Branch (23:5): [True: 0, False: 0]
|
24 | 0 | return ds; |
25 | 0 | } |
26 | | |
27 | | FUZZ_TARGET(script_flags) |
28 | 0 | { |
29 | 0 | if (buffer.size() > 100'000) return; Branch (29:9): [True: 0, False: 0]
|
30 | 0 | SpanReader ds{buffer}; |
31 | 0 | try { |
32 | 0 | const CTransaction tx(deserialize, TX_WITH_WITNESS, ds); |
33 | |
|
34 | 0 | script_verify_flags verify_flags; |
35 | 0 | ds >> verify_flags; |
36 | |
|
37 | 0 | assert(verify_flags == script_verify_flags::from_int(verify_flags.as_int())); Branch (37:9): [True: 0, False: 0]
|
38 | | |
39 | 0 | if (!IsValidFlagCombination(verify_flags)) return; Branch (39:13): [True: 0, False: 0]
|
40 | | |
41 | 0 | script_verify_flags fuzzed_flags; |
42 | 0 | ds >> fuzzed_flags; |
43 | |
|
44 | 0 | std::vector<CTxOut> spent_outputs; |
45 | 0 | for (unsigned i = 0; i < tx.vin.size(); ++i) { Branch (45:30): [True: 0, False: 0]
|
46 | 0 | CTxOut prevout; |
47 | 0 | ds >> prevout; |
48 | 0 | if (!MoneyRange(prevout.nValue)) { Branch (48:17): [True: 0, False: 0]
|
49 | | // prevouts should be consensus-valid |
50 | 0 | prevout.nValue = 1; |
51 | 0 | } |
52 | 0 | spent_outputs.push_back(prevout); |
53 | 0 | } |
54 | 0 | PrecomputedTransactionData txdata; |
55 | 0 | txdata.Init(tx, std::move(spent_outputs)); |
56 | |
|
57 | 0 | for (unsigned i = 0; i < tx.vin.size(); ++i) { Branch (57:30): [True: 0, False: 0]
|
58 | 0 | const CTxOut& prevout = txdata.m_spent_outputs.at(i); |
59 | 0 | const TransactionSignatureChecker checker{&tx, i, prevout.nValue, txdata, MissingDataBehavior::ASSERT_FAIL}; |
60 | |
|
61 | 0 | ScriptError serror; |
62 | 0 | const bool ret = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror); |
63 | 0 | assert(ret == (serror == SCRIPT_ERR_OK)); Branch (63:13): [True: 0, False: 0]
|
64 | | |
65 | | // Verify that removing flags from a passing test or adding flags to a failing test does not change the result |
66 | 0 | if (ret) { Branch (66:17): [True: 0, False: 0]
|
67 | 0 | verify_flags &= ~fuzzed_flags; |
68 | 0 | } else { |
69 | 0 | verify_flags |= fuzzed_flags; |
70 | 0 | } |
71 | 0 | if (!IsValidFlagCombination(verify_flags)) return; Branch (71:17): [True: 0, False: 0]
|
72 | | |
73 | 0 | ScriptError serror_fuzzed; |
74 | 0 | const bool ret_fuzzed = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror_fuzzed); |
75 | 0 | assert(ret_fuzzed == (serror_fuzzed == SCRIPT_ERR_OK)); Branch (75:13): [True: 0, False: 0]
|
76 | | |
77 | 0 | assert(ret_fuzzed == ret); Branch (77:13): [True: 0, False: 0]
|
78 | 0 | } |
79 | 0 | } catch (const std::ios_base::failure&) { |
80 | 0 | return; |
81 | 0 | } |
82 | 0 | } |