Branch data Line data Source code
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 <core_io.h>
6 : :
7 : : #include <primitives/block.h> // IWYU pragma: keep
8 : : #include <primitives/transaction.h>
9 : : #include <script/interpreter.h>
10 : : #include <script/script.h>
11 : : #include <serialize.h>
12 : : #include <streams.h>
13 : : #include <util/result.h>
14 : : #include <util/strencodings.h>
15 : : #include <util/string.h>
16 : : #include <util/translation.h>
17 : :
18 : : #include <algorithm>
19 : : #include <compare>
20 : : #include <cstdint>
21 : : #include <exception>
22 : : #include <map>
23 : : #include <optional>
24 : : #include <span>
25 : : #include <stdexcept>
26 : : #include <utility>
27 : : #include <vector>
28 : :
29 : : using util::SplitString;
30 : :
31 : : namespace {
32 : : class OpCodeParser
33 : : {
34 : : private:
35 : : std::map<std::string, opcodetype> mapOpNames;
36 : :
37 : : public:
38 : 1 : OpCodeParser()
39 : 1 : {
40 [ + + ]: 187 : for (unsigned int op = 0; op <= MAX_OPCODE; ++op) {
41 : : // Allow OP_RESERVED to get into mapOpNames
42 [ + + ]: 186 : if (op < OP_NOP && op != OP_RESERVED) {
43 : 96 : continue;
44 : : }
45 : :
46 [ + - ]: 90 : std::string strName = GetOpName(static_cast<opcodetype>(op));
47 [ - + ]: 90 : if (strName == "OP_UNKNOWN") {
48 : 0 : continue;
49 : : }
50 [ + - ]: 90 : mapOpNames[strName] = static_cast<opcodetype>(op);
51 : : // Convenience: OP_ADD and just ADD are both recognized:
52 [ - + + - ]: 90 : if (strName.starts_with("OP_")) {
53 [ + - + - ]: 90 : mapOpNames[strName.substr(3)] = static_cast<opcodetype>(op);
54 : : }
55 : 90 : }
56 : 1 : }
57 : 5787 : opcodetype Parse(const std::string& s) const
58 : : {
59 : 5787 : auto it = mapOpNames.find(s);
60 [ + + + - ]: 5787 : if (it == mapOpNames.end()) throw std::runtime_error("script parse error: unknown opcode");
61 : 5601 : return it->second;
62 : : }
63 : : };
64 : :
65 : 5787 : opcodetype ParseOpCode(const std::string& s)
66 : : {
67 [ + + + - : 5789 : static const OpCodeParser ocp;
+ - ]
68 : 5787 : return ocp.Parse(s);
69 : : }
70 : :
71 : : } // namespace
72 : :
73 : 334 : CScript ParseScript(const std::string& s)
74 : : {
75 : 334 : CScript result;
76 : :
77 [ - + + - ]: 334 : std::vector<std::string> words = SplitString(s, " \t\n");
78 : :
79 [ + + ]: 367752 : for (const std::string& w : words) {
80 [ + + ]: 367644 : if (w.empty()) {
81 : : // Empty string, ignore. (SplitString doesn't combine multiple separators)
82 [ - + + - : 330372 : } else if (std::all_of(w.begin(), w.end(), ::IsDigit) ||
+ + ]
83 [ + + + + : 166653 : (w.front() == '-' && w.size() > 1 && std::all_of(w.begin() + 1, w.end(), ::IsDigit)))
+ - + + ]
84 : : {
85 : : // Number
86 [ - + ]: 211070 : const auto num{ToIntegral<int64_t>(w)};
87 : :
88 : : // limit the range of numbers ParseScript accepts in decimal
89 : : // since numbers outside -0xFFFFFFFF...0xFFFFFFFF are illegal in scripts
90 [ + + + + : 211070 : if (!num.has_value() || num > int64_t{0xffffffff} || num < -1 * int64_t{0xffffffff}) {
+ + ]
91 : 40 : throw std::runtime_error("script parse error: decimal numeric value only allowed in the "
92 [ + - ]: 40 : "range -0xFFFFFFFF...0xFFFFFFFF");
93 : : }
94 : :
95 [ + - ]: 367418 : result << num.value();
96 [ - + + + : 151459 : } else if (w.starts_with("0x") && w.size() > 2 && IsHex(std::string(w.begin() + 2, w.end()))) {
+ + + - -
+ + - + +
+ + - - ]
97 : : // Raw hex data, inserted NOT pushed onto stack:
98 [ - + + - : 21370 : std::vector<unsigned char> raw = ParseHex(std::string(w.begin() + 2, w.end()));
- + + - ]
99 : 10685 : result.insert(result.end(), raw.begin(), raw.end());
100 [ - + + + : 119302 : } else if (w.size() >= 2 && w.front() == '\'' && w.back() == '\'') {
+ + + + ]
101 : : // Single-quoted string, pushed as data. NOTE: this is poor-man's
102 : : // parsing, spaces/tabs/newlines in single-quoted strings won't work.
103 [ + - ]: 102830 : std::vector<unsigned char> value(w.begin() + 1, w.end() - 1);
104 [ - + ]: 102830 : result << value;
105 : 102830 : } else {
106 : : // opcode, e.g. OP_ADD or ADD:
107 [ + + + - ]: 5787 : result << ParseOpCode(w);
108 : : }
109 : : }
110 : :
111 : 108 : return result;
112 : 334 : }
113 : :
114 : : // Check that all of the input and output scripts of a transaction contains valid opcodes
115 : 8392 : static bool CheckTxScriptsSanity(const CMutableTransaction& tx)
116 : : {
117 : : // Check input scripts for non-coinbase txs
118 [ + + ]: 16784 : if (!CTransaction(tx).IsCoinBase()) {
119 [ - + + + ]: 32967 : for (unsigned int i = 0; i < tx.vin.size(); i++) {
120 [ + + + + : 28170 : if (!tx.vin[i].scriptSig.HasValidOps() || tx.vin[i].scriptSig.size() > MAX_SCRIPT_SIZE) {
+ + ]
121 : : return false;
122 : : }
123 : : }
124 : : }
125 : : // Check output scripts
126 [ - + + + ]: 239907 : for (unsigned int i = 0; i < tx.vout.size(); i++) {
127 [ + + + + : 235879 : if (!tx.vout[i].scriptPubKey.HasValidOps() || tx.vout[i].scriptPubKey.size() > MAX_SCRIPT_SIZE) {
+ + ]
128 : : return false;
129 : : }
130 : : }
131 : :
132 : : return true;
133 : : }
134 : :
135 : 8813 : static bool DecodeTx(CMutableTransaction& tx, const std::vector<unsigned char>& tx_data, bool try_no_witness, bool try_witness)
136 : : {
137 : : // General strategy:
138 : : // - Decode both with extended serialization (which interprets the 0x0001 tag as a marker for
139 : : // the presence of witnesses) and with legacy serialization (which interprets the tag as a
140 : : // 0-input 1-output incomplete transaction).
141 : : // - Restricted by try_no_witness (which disables legacy if false) and try_witness (which
142 : : // disables extended if false).
143 : : // - Ignore serializations that do not fully consume the hex string.
144 : : // - If neither succeeds, fail.
145 : : // - If only one succeeds, return that one.
146 : : // - If both decode attempts succeed:
147 : : // - If only one passes the CheckTxScriptsSanity check, return that one.
148 : : // - If neither or both pass CheckTxScriptsSanity, return the extended one.
149 : :
150 [ + - ]: 8813 : CMutableTransaction tx_extended, tx_legacy;
151 : 8813 : bool ok_extended = false, ok_legacy = false;
152 : :
153 : : // Try decoding with extended serialization support, and remember if the result successfully
154 : : // consumes the entire input.
155 [ + + ]: 8813 : if (try_witness) {
156 [ - + + - ]: 7651 : DataStream ssData(tx_data);
157 : 7651 : try {
158 [ + + ]: 7651 : ssData >> TX_WITH_WITNESS(tx_extended);
159 [ - + + + ]: 7436 : if (ssData.empty()) ok_extended = true;
160 [ - + ]: 215 : } catch (const std::exception&) {
161 : : // Fall through.
162 : 215 : }
163 : 0 : }
164 : :
165 : : // Optimization: if extended decoding succeeded and the result passes CheckTxScriptsSanity,
166 : : // don't bother decoding the other way.
167 [ + + + - : 7651 : if (ok_extended && CheckTxScriptsSanity(tx_extended)) {
+ + ]
168 : 3812 : tx = std::move(tx_extended);
169 : 3812 : return true;
170 : : }
171 : :
172 : : // Try decoding with legacy serialization, and remember if the result successfully consumes the entire input.
173 [ + + ]: 5001 : if (try_no_witness) {
174 [ - + + - ]: 1427 : DataStream ssData(tx_data);
175 : 1427 : try {
176 [ + + ]: 1427 : ssData >> TX_NO_WITNESS(tx_legacy);
177 [ - + + + ]: 1251 : if (ssData.empty()) ok_legacy = true;
178 [ - + ]: 176 : } catch (const std::exception&) {
179 : : // Fall through.
180 : 176 : }
181 : 0 : }
182 : :
183 : : // If legacy decoding succeeded and passes CheckTxScriptsSanity, that's our answer, as we know
184 : : // at this point that extended decoding either failed or doesn't pass the sanity check.
185 [ + + + - : 1427 : if (ok_legacy && CheckTxScriptsSanity(tx_legacy)) {
+ + ]
186 : 216 : tx = std::move(tx_legacy);
187 : 216 : return true;
188 : : }
189 : :
190 : : // If extended decoding succeeded, and neither decoding passes sanity, return the extended one.
191 [ + + ]: 4785 : if (ok_extended) {
192 : 3576 : tx = std::move(tx_extended);
193 : 3576 : return true;
194 : : }
195 : :
196 : : // If legacy decoding succeeded and extended didn't, return the legacy one.
197 [ + + ]: 1209 : if (ok_legacy) {
198 : 221 : tx = std::move(tx_legacy);
199 : 221 : return true;
200 : : }
201 : :
202 : : // If none succeeded, we failed.
203 : : return false;
204 : 17626 : }
205 : :
206 : 8895 : bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness, bool try_witness)
207 : : {
208 [ - + + + ]: 8895 : if (!IsHex(hex_tx)) {
209 : : return false;
210 : : }
211 : :
212 [ - + ]: 8813 : std::vector<unsigned char> txData(ParseHex(hex_tx));
213 [ + - ]: 8813 : return DecodeTx(tx, txData, try_no_witness, try_witness);
214 : 8813 : }
215 : :
216 : 549 : bool DecodeHexBlockHeader(CBlockHeader& header, const std::string& hex_header)
217 : : {
218 [ - + + + ]: 549 : if (!IsHex(hex_header)) return false;
219 : :
220 [ - + ]: 476 : const std::vector<unsigned char> header_data{ParseHex(hex_header)};
221 [ - + + - ]: 476 : DataStream ser_header{header_data};
222 : 476 : try {
223 [ + + ]: 952 : ser_header >> header;
224 [ - + ]: 46 : } catch (const std::exception&) {
225 : 46 : return false;
226 : 46 : }
227 : : return true;
228 : 476 : }
229 : :
230 : 505 : bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
231 : : {
232 [ - + + + ]: 505 : if (!IsHex(strHexBlk))
233 : : return false;
234 : :
235 [ - + ]: 427 : std::vector<unsigned char> blockData(ParseHex(strHexBlk));
236 [ - + + - ]: 427 : DataStream ssBlock(blockData);
237 : 427 : try {
238 [ + + ]: 854 : ssBlock >> TX_WITH_WITNESS(block);
239 : : }
240 [ - + ]: 314 : catch (const std::exception&) {
241 : 314 : return false;
242 : 314 : }
243 : :
244 : : return true;
245 : 427 : }
246 : :
247 : 3273 : util::Result<int> SighashFromStr(const std::string& sighash)
248 : : {
249 : 3273 : static const std::map<std::string, int> map_sighash_values = {
250 [ + - ]: 4 : {std::string("DEFAULT"), int(SIGHASH_DEFAULT)},
251 : 4 : {std::string("ALL"), int(SIGHASH_ALL)},
252 : 4 : {std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)},
253 : 4 : {std::string("NONE"), int(SIGHASH_NONE)},
254 : 4 : {std::string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)},
255 : 4 : {std::string("SINGLE"), int(SIGHASH_SINGLE)},
256 : 4 : {std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)},
257 [ + + + - : 3289 : };
+ + - - ]
258 : 3273 : const auto& it = map_sighash_values.find(sighash);
259 [ + + ]: 3273 : if (it != map_sighash_values.end()) {
260 : 6 : return it->second;
261 : : } else {
262 [ + - + - ]: 13068 : return util::Error{Untranslated("'" + sighash + "' is not a valid sighash parameter.")};
263 : : }
264 [ + - + - : 14 : }
+ - + - +
- + - - +
- - ]
|