Bitcoin Core  31.0.0
P2P Digital Currency
script_flags.cpp
Go to the documentation of this file.
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>
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 
19 {
21  ds >> n;
23  assert(n == f.as_int());
24  return ds;
25 }
26 
27 FUZZ_TARGET(script_flags)
28 {
29  if (buffer.size() > 100'000) return;
30  SpanReader ds{buffer};
31  try {
32  const CTransaction tx(deserialize, TX_WITH_WITNESS, ds);
33 
34  script_verify_flags verify_flags;
35  ds >> verify_flags;
36 
37  assert(verify_flags == script_verify_flags::from_int(verify_flags.as_int()));
38 
39  if (!IsValidFlagCombination(verify_flags)) return;
40 
41  script_verify_flags fuzzed_flags;
42  ds >> fuzzed_flags;
43 
44  std::vector<CTxOut> spent_outputs;
45  for (unsigned i = 0; i < tx.vin.size(); ++i) {
46  CTxOut prevout;
47  ds >> prevout;
48  if (!MoneyRange(prevout.nValue)) {
49  // prevouts should be consensus-valid
50  prevout.nValue = 1;
51  }
52  spent_outputs.push_back(prevout);
53  }
54  PrecomputedTransactionData txdata;
55  txdata.Init(tx, std::move(spent_outputs));
56 
57  for (unsigned i = 0; i < tx.vin.size(); ++i) {
58  const CTxOut& prevout = txdata.m_spent_outputs.at(i);
59  const TransactionSignatureChecker checker{&tx, i, prevout.nValue, txdata, MissingDataBehavior::ASSERT_FAIL};
60 
61  ScriptError serror;
62  const bool ret = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror);
63  assert(ret == (serror == SCRIPT_ERR_OK));
64 
65  // Verify that removing flags from a passing test or adding flags to a failing test does not change the result
66  if (ret) {
67  verify_flags &= ~fuzzed_flags;
68  } else {
69  verify_flags |= fuzzed_flags;
70  }
71  if (!IsValidFlagCombination(verify_flags)) return;
72 
73  ScriptError serror_fuzzed;
74  const bool ret_fuzzed = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror_fuzzed);
75  assert(ret_fuzzed == (serror_fuzzed == SCRIPT_ERR_OK));
76 
77  assert(ret_fuzzed == ret);
78  }
79  } catch (const std::ios_base::failure&) {
80  return;
81  }
82 }
assert(!tx.IsCoinBase())
constexpr value_type as_int() const
Definition: verify_flags.h:36
Minimal stream for reading from an existing byte array by std::span.
Definition: streams.h:82
FUZZ_TARGET(script_flags)
static SpanReader & operator>>(SpanReader &ds, script_verify_flags &f)
static constexpr script_verify_flags from_int(value_type f)
Definition: verify_flags.h:35