Bitcoin Core 22.99.0
P2P Digital Currency
script.cpp
Go to the documentation of this file.
1// Copyright (c) 2019-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 <chainparams.h>
6#include <compressor.h>
7#include <core_io.h>
8#include <core_memusage.h>
9#include <key_io.h>
10#include <policy/policy.h>
11#include <pubkey.h>
12#include <rpc/util.h>
13#include <script/descriptor.h>
14#include <script/interpreter.h>
15#include <script/script.h>
16#include <script/script_error.h>
17#include <script/sign.h>
19#include <script/standard.h>
20#include <streams.h>
22#include <test/fuzz/fuzz.h>
23#include <test/fuzz/util.h>
24#include <univalue.h>
25
26#include <algorithm>
27#include <cassert>
28#include <cstdint>
29#include <optional>
30#include <string>
31#include <vector>
32
34{
35 // Fuzzers using pubkey must hold an ECCVerifyHandle.
36 static const ECCVerifyHandle verify_handle;
37
39}
40
42{
43 FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
44 const std::optional<CScript> script_opt = ConsumeDeserializable<CScript>(fuzzed_data_provider);
45 if (!script_opt) return;
46 const CScript script{*script_opt};
47
48 CompressedScript compressed;
49 if (CompressScript(script, compressed)) {
50 const unsigned int size = compressed[0];
51 compressed.erase(compressed.begin());
52 assert(size <= 5);
53 CScript decompressed_script;
54 const bool ok = DecompressScript(decompressed_script, size, compressed);
55 assert(ok);
56 assert(script == decompressed_script);
57 }
58
59 TxoutType which_type;
60 bool is_standard_ret = IsStandard(script, which_type);
61 if (!is_standard_ret) {
62 assert(which_type == TxoutType::NONSTANDARD ||
63 which_type == TxoutType::NULL_DATA ||
64 which_type == TxoutType::MULTISIG);
65 }
66 if (which_type == TxoutType::NONSTANDARD) {
67 assert(!is_standard_ret);
68 }
69 if (which_type == TxoutType::NULL_DATA) {
70 assert(script.IsUnspendable());
71 }
72 if (script.IsUnspendable()) {
73 assert(which_type == TxoutType::NULL_DATA ||
74 which_type == TxoutType::NONSTANDARD);
75 }
76
77 CTxDestination address;
78 bool extract_destination_ret = ExtractDestination(script, address);
79 if (!extract_destination_ret) {
80 assert(which_type == TxoutType::PUBKEY ||
81 which_type == TxoutType::NONSTANDARD ||
82 which_type == TxoutType::NULL_DATA ||
83 which_type == TxoutType::MULTISIG);
84 }
85 if (which_type == TxoutType::NONSTANDARD ||
86 which_type == TxoutType::NULL_DATA ||
87 which_type == TxoutType::MULTISIG) {
88 assert(!extract_destination_ret);
89 }
90
91 const FlatSigningProvider signing_provider;
92 (void)InferDescriptor(script, signing_provider);
93 (void)IsSegWitOutput(signing_provider, script);
94 (void)IsSolvable(signing_provider, script);
95
96 (void)RecursiveDynamicUsage(script);
97
98 std::vector<std::vector<unsigned char>> solutions;
99 (void)Solver(script, solutions);
100
101 (void)script.HasValidOps();
102 (void)script.IsPayToScriptHash();
103 (void)script.IsPayToWitnessScriptHash();
104 (void)script.IsPushOnly();
105 (void)script.GetSigOpCount(/* fAccurate= */ false);
106
107 (void)FormatScript(script);
108 (void)ScriptToAsmStr(script, false);
109 (void)ScriptToAsmStr(script, true);
110
112 ScriptPubKeyToUniv(script, o1, true);
114 ScriptPubKeyToUniv(script, o2, false);
116 ScriptToUniv(script, o3);
117
118 {
119 const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
120 CompressedScript compressed_script;
121 compressed_script.assign(bytes.begin(), bytes.end());
122 // DecompressScript(..., ..., bytes) is not guaranteed to be defined if the bytes vector is too short
123 if (compressed_script.size() >= 32) {
124 CScript decompressed_script;
125 DecompressScript(decompressed_script, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), compressed_script);
126 }
127 }
128
129 const std::optional<CScript> other_script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
130 if (other_script) {
131 {
132 CScript script_mut{script};
133 (void)FindAndDelete(script_mut, *other_script);
134 }
135 const std::vector<std::string> random_string_vector = ConsumeRandomLengthStringVector(fuzzed_data_provider);
136 const uint32_t u32{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
137 const uint32_t flags{u32 | SCRIPT_VERIFY_P2SH};
138 {
139 CScriptWitness wit;
140 for (const auto& s : random_string_vector) {
141 wit.stack.emplace_back(s.begin(), s.end());
142 }
143 (void)CountWitnessSigOps(script, *other_script, &wit, flags);
144 wit.SetNull();
145 }
146 }
147
148 (void)GetOpName(ConsumeOpcodeType(fuzzed_data_provider));
149 (void)ScriptErrorString(static_cast<ScriptError>(fuzzed_data_provider.ConsumeIntegralInRange<int>(0, SCRIPT_ERR_ERROR_COUNT)));
150
151 {
152 const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
153 CScript append_script{bytes.begin(), bytes.end()};
154 append_script << fuzzed_data_provider.ConsumeIntegral<int64_t>();
155 append_script << ConsumeOpcodeType(fuzzed_data_provider);
156 append_script << CScriptNum{fuzzed_data_provider.ConsumeIntegral<int64_t>()};
157 append_script << ConsumeRandomLengthByteVector(fuzzed_data_provider);
158 }
159
160 {
161 const CTxDestination tx_destination_1{
162 fuzzed_data_provider.ConsumeBool() ?
163 DecodeDestination(fuzzed_data_provider.ConsumeRandomLengthString()) :
164 ConsumeTxDestination(fuzzed_data_provider)};
165 const CTxDestination tx_destination_2{ConsumeTxDestination(fuzzed_data_provider)};
166 const std::string encoded_dest{EncodeDestination(tx_destination_1)};
167 const UniValue json_dest{DescribeAddress(tx_destination_1)};
168 Assert(tx_destination_1 == DecodeDestination(encoded_dest));
169 (void)GetKeyForDestination(/* store */ {}, tx_destination_1);
170 const CScript dest{GetScriptForDestination(tx_destination_1)};
171 const bool valid{IsValidDestination(tx_destination_1)};
172 Assert(dest.empty() != valid);
173
174 Assert(valid == IsValidDestinationString(encoded_dest));
175
176 (void)(tx_destination_1 < tx_destination_2);
177 if (tx_destination_1 == tx_destination_2) {
178 Assert(encoded_dest == EncodeDestination(tx_destination_2));
179 Assert(json_dest.write() == DescribeAddress(tx_destination_2).write());
180 Assert(dest == GetScriptForDestination(tx_destination_2));
181 }
182 }
183}
int flags
Definition: bitcoin-tx.cpp:525
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given chain name.
#define Assert(val)
Identity function.
Definition: check.h:57
static const std::string REGTEST
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:406
Users of this module must hold an ECCVerifyHandle.
Definition: pubkey.h:316
std::string ConsumeRandomLengthString(size_t max_length)
T ConsumeIntegralInRange(T min, T max)
@ VOBJ
Definition: univalue.h:19
Implements a drop-in replacement for std::vector<T> which stores up to N elements directly (without h...
Definition: prevector.h:37
size_type size() const
Definition: prevector.h:282
iterator erase(iterator pos)
Definition: prevector.h:401
iterator begin()
Definition: prevector.h:290
void assign(size_type n, const T &val)
Definition: prevector.h:218
bool DecompressScript(CScript &script, unsigned int nSize, const CompressedScript &in)
Definition: compressor.cpp:95
bool CompressScript(const CScript &script, CompressedScript &out)
Definition: compressor.cpp:55
std::string FormatScript(const CScript &script)
Definition: core_write.cpp:34
std::string ScriptToAsmStr(const CScript &script, const bool fAttemptSighashDecode=false)
Create the assembly string representation of a CScript object.
Definition: core_write.cpp:93
void ScriptPubKeyToUniv(const CScript &scriptPubKey, UniValue &out, bool include_hex, bool include_address=true)
Definition: core_write.cpp:150
void ScriptToUniv(const CScript &script, UniValue &out)
Definition: core_write.cpp:145
static size_t RecursiveDynamicUsage(const CScript &script)
Definition: core_memusage.h:12
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
int FindAndDelete(CScript &script, const CScript &b)
size_t CountWitnessSigOps(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, unsigned int flags)
@ SCRIPT_VERIFY_P2SH
Definition: interpreter.h:46
bool IsValidDestinationString(const std::string &str, const CChainParams &params)
Definition: key_io.cpp:272
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:256
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg)
Definition: key_io.cpp:261
bool IsStandard(const CScript &scriptPubKey, TxoutType &whichType)
Definition: policy.cpp:58
UniValue DescribeAddress(const CTxDestination &dest)
Definition: util.cpp:325
std::string GetOpName(opcodetype opcode)
Definition: script.cpp:12
std::string ScriptErrorString(const ScriptError serror)
enum ScriptError_t ScriptError
@ SCRIPT_ERR_ERROR_COUNT
Definition: script_error.h:85
bool IsSegWitOutput(const SigningProvider &provider, const CScript &script)
Check whether a scriptPubKey is known to be segwit.
Definition: sign.cpp:600
bool IsSolvable(const SigningProvider &provider, const CScript &script)
Definition: sign.cpp:581
CKeyID GetKeyForDestination(const SigningProvider &store, const CTxDestination &dest)
Return the CKeyID of the key involved in a script (if there is a unique one).
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
Definition: standard.cpp:144
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:213
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:332
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:310
TxoutType
Definition: standard.h:59
@ NULL_DATA
unspendable OP_RETURN script that carries data
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:157
std::vector< std::vector< unsigned char > > stack
Definition: script.h:561
void SetNull()
Definition: script.h:568
FUZZ_TARGET_INIT(script, initialize_script)
Definition: script.cpp:41
void initialize_script()
Definition: script.cpp:33
CTxDestination ConsumeTxDestination(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: util.cpp:310
std::vector< std::string > ConsumeRandomLengthStringVector(FuzzedDataProvider &fuzzed_data_provider, const size_t max_vector_size=16, const size_t max_string_length=16) noexcept
Definition: util.h:79
opcodetype ConsumeOpcodeType(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: util.h:122
std::vector< uint8_t > ConsumeRandomLengthByteVector(FuzzedDataProvider &fuzzed_data_provider, const std::optional< size_t > &max_length=std::nullopt) noexcept
Definition: util.h:61
assert(!tx.IsCoinBase())