Line data Source code
1 : // Copyright (c) 2009-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 <core_io.h>
6 :
7 : #include <primitives/block.h>
8 : #include <primitives/transaction.h>
9 : #include <script/script.h>
10 : #include <script/sign.h>
11 : #include <serialize.h>
12 : #include <streams.h>
13 : #include <univalue.h>
14 : #include <util/string.h>
15 : #include <util/strencodings.h>
16 : #include <version.h>
17 :
18 : #include <algorithm>
19 : #include <string>
20 :
21 : namespace {
22 : class OpCodeParser
23 : {
24 : private:
25 : std::map<std::string, opcodetype> mapOpNames;
26 :
27 : public:
28 16 : OpCodeParser()
29 8 : {
30 1512 : for (unsigned int op = 0; op <= MAX_OPCODE; ++op) {
31 : // Allow OP_RESERVED to get into mapOpNames
32 1504 : if (op < OP_NOP && op != OP_RESERVED) {
33 768 : continue;
34 : }
35 :
36 736 : std::string strName = GetOpName(static_cast<opcodetype>(op));
37 736 : if (strName == "OP_UNKNOWN") {
38 0 : continue;
39 : }
40 736 : mapOpNames[strName] = static_cast<opcodetype>(op);
41 : // Convenience: OP_ADD and just ADD are both recognized:
42 736 : if (strName.starts_with("OP_")) {
43 736 : mapOpNames[strName.substr(3)] = static_cast<opcodetype>(op);
44 736 : }
45 736 : }
46 16 : }
47 4015 : opcodetype Parse(const std::string& s) const
48 : {
49 4015 : auto it = mapOpNames.find(s);
50 4015 : if (it == mapOpNames.end()) throw std::runtime_error("script parse error: unknown opcode");
51 4013 : return it->second;
52 0 : }
53 : };
54 :
55 4015 : opcodetype ParseOpCode(const std::string& s)
56 : {
57 4015 : static const OpCodeParser ocp;
58 4015 : return ocp.Parse(s);
59 0 : }
60 :
61 : } // namespace
62 :
63 2779 : CScript ParseScript(const std::string& s)
64 : {
65 2779 : CScript result;
66 :
67 :
68 2779 : std::vector<std::string> words = SplitString(s, " \t\n");
69 :
70 15184 : for (const std::string& w : words) {
71 12414 : if (w.empty()) {
72 : // Empty string, ignore. (SplitString doesn't combine multiple separators)
73 19991 : } else if (std::all_of(w.begin(), w.end(), ::IsDigit) ||
74 7577 : (w.front() == '-' && w.size() > 1 && std::all_of(w.begin() + 1, w.end(), ::IsDigit)))
75 : {
76 : // Number
77 4793 : const auto num{ToIntegral<int64_t>(w)};
78 :
79 : // limit the range of numbers ParseScript accepts in decimal
80 : // since numbers outside -0xFFFFFFFF...0xFFFFFFFF are illegal in scripts
81 4793 : if (!num.has_value() || num > int64_t{0xffffffff} || num < -1 * int64_t{0xffffffff}) {
82 7 : throw std::runtime_error("script parse error: decimal numeric value only allowed in the "
83 : "range -0xFFFFFFFF...0xFFFFFFFF");
84 : }
85 :
86 4786 : result << num.value();
87 14393 : } else if (w.substr(0, 2) == "0x" && w.size() > 2 && IsHex(std::string(w.begin() + 2, w.end()))) {
88 : // Raw hex data, inserted NOT pushed onto stack:
89 2151 : std::vector<unsigned char> raw = ParseHex(std::string(w.begin() + 2, w.end()));
90 2151 : result.insert(result.end(), raw.begin(), raw.end());
91 7456 : } else if (w.size() >= 2 && w.front() == '\'' && w.back() == '\'') {
92 : // Single-quoted string, pushed as data. NOTE: this is poor-man's
93 : // parsing, spaces/tabs/newlines in single-quoted strings won't work.
94 1290 : std::vector<unsigned char> value(w.begin() + 1, w.end() - 1);
95 1290 : result << value;
96 1290 : } else {
97 : // opcode, e.g. OP_ADD or ADD:
98 4015 : result << ParseOpCode(w);
99 : }
100 : }
101 :
102 2770 : return result;
103 2779 : }
104 :
105 21 : static bool DecodeTx(CMutableTransaction& tx, const std::vector<unsigned char>& tx_data)
106 : {
107 21 : CDataStream ssData(tx_data, SER_NETWORK, PROTOCOL_VERSION);
108 : try {
109 21 : ssData >> tx;
110 19 : if (!ssData.empty()) {
111 0 : return false;
112 : }
113 21 : } catch (const std::exception&) {
114 2 : return false;
115 2 : }
116 :
117 19 : return true;
118 23 : }
119 :
120 23 : bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx)
121 : {
122 23 : if (!IsHex(hex_tx)) {
123 2 : return false;
124 : }
125 :
126 21 : std::vector<unsigned char> txData(ParseHex(hex_tx));
127 21 : return DecodeTx(tx, txData);
128 23 : }
129 :
130 1 : bool DecodeHexBlockHeader(CBlockHeader& header, const std::string& hex_header)
131 : {
132 1 : if (!IsHex(hex_header)) return false;
133 :
134 1 : const std::vector<unsigned char> header_data{ParseHex(hex_header)};
135 1 : CDataStream ser_header(header_data, SER_NETWORK, PROTOCOL_VERSION);
136 : try {
137 1 : ser_header >> header;
138 1 : } catch (const std::exception&) {
139 1 : return false;
140 1 : }
141 0 : return true;
142 2 : }
143 :
144 7 : bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
145 : {
146 7 : if (!IsHex(strHexBlk))
147 0 : return false;
148 :
149 7 : std::vector<unsigned char> blockData(ParseHex(strHexBlk));
150 7 : CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION);
151 : try {
152 7 : ssBlock >> block;
153 7 : }
154 : catch (const std::exception&) {
155 0 : return false;
156 0 : }
157 :
158 7 : return true;
159 7 : }
160 :
161 58 : bool ParseHashStr(const std::string& strHex, uint256& result)
162 : {
163 58 : if ((strHex.size() != 64) || !IsHex(strHex))
164 6 : return false;
165 :
166 52 : result.SetHex(strHex);
167 52 : return true;
168 58 : }
169 :
170 3 : std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName)
171 : {
172 3 : std::string strHex;
173 3 : if (v.isStr())
174 3 : strHex = v.getValStr();
175 3 : if (!IsHex(strHex))
176 0 : throw std::runtime_error(strName + " must be hexadecimal string (not '" + strHex + "')");
177 3 : return ParseHex(strHex);
178 3 : }
179 :
180 2 : int ParseSighashString(const UniValue& sighash)
181 : {
182 2 : int hash_type = SIGHASH_ALL;
183 2 : if (!sighash.isNull()) {
184 0 : static std::map<std::string, int> map_sighash_values = {
185 0 : {std::string("ALL"), int(SIGHASH_ALL)},
186 0 : {std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)},
187 0 : {std::string("NONE"), int(SIGHASH_NONE)},
188 0 : {std::string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)},
189 0 : {std::string("SINGLE"), int(SIGHASH_SINGLE)},
190 0 : {std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)},
191 : };
192 0 : const std::string& strHashType = sighash.get_str();
193 0 : const auto& it = map_sighash_values.find(strHashType);
194 0 : if (it != map_sighash_values.end()) {
195 0 : hash_type = it->second;
196 0 : } else {
197 0 : throw std::runtime_error(strHashType + " is not a valid sighash parameter.");
198 : }
199 0 : }
200 2 : return hash_type;
201 0 : }
|